在 Intel AppUp SDK Developer's Guide 中,有不少的篇幅都是在講應用程式和 SDK 一些函式的整合,以將 AppUp Center 的機能和應用程式整合在一起,像是 Application Registration, Instrumentation (Events), Upgrade 與 Crash Report 等,除了之前我所發表的使用 Exception 決定 Crash Report 的功能外,我們還可以進一步的將 SDK 的函式包裝起來,讓在整合 SDK 和應用程式的過程能更簡單,簡單到什麼程度呢 ... 只要使用一個類別即可,而且相關的 Exception 都會轉換成自訂的 Crash Report。
在 Intel AppUp SDK Developer's Guide 中,有不少的篇幅都是在講應用程式和 SDK 一些函式的整合,以將 AppUp Center 的機能和應用程式整合在一起,像是 Application Registration, Instrumentation (Events), Upgrade 與 Crash Report 等,除了之前我所發表的使用 Exception 決定 Crash Report 的功能外,我們還可以進一步的將 SDK 的函式包裝起來,讓在整合 SDK 和應用程式的過程能更簡單,簡單到什麼程度呢 ... 只要使用一個類別即可,而且相關的 Exception 都會轉換成自訂的 Crash Report。
下圖為 IADP 應用程式的運行架構,圖中的 Developer Platform 和 Consumer Platform 中的 Application 就是我們要開發的 IADP-Compliant 應用程式所使用的資源與架構。
我們以 Windows Forms 來做例子,當產生 Windows Forms 專案時,都會有一個 Program.cs,裡面會放初始化 Windows Forms 應用程式的程式碼,不過最多也只是這樣:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
然後 SDK 的 Developer's Guide 上說,我們要在程式中加入 AdpLibrary 的 Reference,使用 AdpApplication 建構式傳入 Application ID 以註冊應用程式,若有錯誤的話要處理 (捕捉 AdpErrorException 和檢查 ADP_RET_CODE 是屬於哪種例外),而且還要自己維護一個 AdpApplication 的全域變數,再做其他的事 (ex: BeginEvent(), EndEvent(), ...),這些事都要由開發人員來做,老實說是挺煩人的。
所以才會有一個構想:我可以有一個類別可以幫我管這些事,而且盡量的減少要變動的程式碼,那該有多好?我試著把這個構想給實現,不過想要減少變動的程式碼並不容易,因為例外處理的變動比較大,所以我目前可以做到的就是把該處理的例外事件化,而我們更可集中火力在 Program.cs,而不會去改動現有的表單或模組的程式邏輯。例如這樣:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
IadpApplicationContext context = new IadpApplicationContext(new frmMain(), new com.intel.adp.AdpApplicationId(0x01, 0x01, 0x01, 0x01));
context.InitializationFailedEvent += (sender, e) =>
{
// TODO: implement application logic for SDK initialization error occurred.
};
context.RuntimeErrorEvent += (sender, e) =>
{
// TODO: implement application logic for SDK runtime error occurred.
};
context.UnauthorizedEvent += (sender, e) =>
{
MessageBox.Show(
"This application's key is invalid or unauthorized, please contact to author of this application.",
"Application Key is invalid or unauthorized.", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.ExitThread();
Application.Exit();
};
context.WarningErrorEvent += (sender, e) =>
{
// TODO: implement application logic for SDK warning error occurred.
};
context.InitAdpApplication();
context.Run();
}
}
這段程式碼就已經做完了 SDK 所需的工作,包含註冊 Application ID,處理應該處理的例外 (event-based),以及做一些初始處理 (包含設定 Exception-based Crash Report) 等,應用程式也會自己保有訊息迴圈,以保持應用程式自己的訊息處理與應用程式生命週期等。而一切的核心就是 IadpApplicationContext,這個類別是衍生自 Windows Forms 本身的 ApplicationContext 類別,並且在內部直接使用 Application 類別做應用程式的接續處理,如此開發人員只要把焦點放在怎麼處理 SDK 的例外以及自己本身的應用程式邏輯即可,不需要再對與 SDK 整合這件事傷腦筋了。
下列為 IadpApplicationContext 的完整程式碼,裡面使用到了像是 delegate 與 event 的作法,以及自訂 Exception EventArgs 的作法:
/// <summary>
/// Exception Event Args.
/// </summary>
public class IadpExceptionEventArgs : EventArgs
{
/// <summary>
/// Exception Instance for Error Event.
/// </summary>
public IadpSDKException Exception { get; set; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="e">Exception Instance for Error Event.</param>
public IadpExceptionEventArgs(IadpSDKException e)
{
this.Exception = e;
}
}
/// <summary>
/// Fire this event when Unauthorized exception of IADP SDK occurred.
/// </summary>
/// <param name="sender">Event Firer, mean Application Context Class</param>
/// <param name="e">Unauthorized Exception Data.</param>
public delegate void IadpAppUnauthorizedEvent(object sender, IadpExceptionEventArgs e);
/// <summary>
/// Fire this event when Initialization Failed exception of IADP SDK occurred.
/// </summary>
/// <param name="sender">Event Firer, mean Application Context Class</param>
/// <param name="e">Initialization Failed Exception Data.</param>
public delegate void IadpAppInitializationFailedEvent(object sender, IadpExceptionEventArgs e);
/// <summary>
/// Fire this event when Runtime exception of IADP SDK occurred.
/// </summary>
/// <param name="sender">Event Firer, mean Application Context Class</param>
/// <param name="e">Runtime Exception Data.</param>
public delegate void IadpAppRuntimeErrorEvent(object sender, IadpExceptionEventArgs e);
/// <summary>
/// Fire this event when Warning exception of IADP SDK occurred.
/// </summary>
/// <param name="sender">Event Firer, mean Application Context Class</param>
/// <param name="e">Warning Exception Data.</param>
public delegate void IadpWarningErrorEvent(object sender, IadpExceptionEventArgs e);
/// <summary>
/// EasyIADP Application Context Wrapper.
/// </summary>
public class IadpApplicationContext : ApplicationContext
{
private AdpApplication _adpApplication = null;
private AdpApplicationId _adpApplicationID;
private bool _initCompleted = false;
/// <summary>
/// Fire this event when Runtime exception of IADP SDK occurred.
/// </summary>
public event IadpAppInitializationFailedEvent InitializationFailedEvent;
/// <summary>
/// Fire this event when Unauthorized exception of IADP SDK occurred.
/// </summary>
public event IadpAppUnauthorizedEvent UnauthorizedEvent;
/// <summary>
/// Fire this event when Runtime exception of IADP SDK occurred.
/// </summary>
public event IadpAppRuntimeErrorEvent RuntimeErrorEvent;
/// <summary>
/// Fire this event when Warning exception of IADP SDK occurred.
/// </summary>
public event IadpWarningErrorEvent WarningErrorEvent;
/// <summary>
/// Constructor.
/// </summary>
public IadpApplicationContext()
: base()
{
this._adpApplicationID = AdpConstants.ADP_DEBUG_APPLICATIONID;
}
/// <summary>
/// Constructor for Specified application ID.
/// </summary>
/// <param name="ApplicationID">Application ID.</param>
/// <remarks>
/// If your application is under debugging, please use ADP_DEBUG_APPLICATIONID, otherwise use the ID provided by Intel.
/// </remarks>
public IadpApplicationContext(AdpApplicationId ApplicationID)
: base()
{
this._adpApplicationID = ApplicationID;
}
/// <summary>
/// Constructor for Startup Form.
/// </summary>
/// <param name="MainForm">Startup Form.</param>
public IadpApplicationContext(Form MainForm)
: base(MainForm)
{
this._adpApplicationID = AdpConstants.ADP_DEBUG_APPLICATIONID;
}
/// <summary>
/// Constructor for Startup Form and Specified Application ID.
/// </summary>
/// <param name="MainForm">Startup Form.</param>
/// <param name="ApplicationID">Application ID.</param>
/// <remarks>
/// If your application will submit to Intel, please use this constructor to initialize application.
/// </remarks>
public IadpApplicationContext(Form MainForm, AdpApplicationId ApplicationID)
: base(MainForm)
{
this._adpApplicationID = ApplicationID;
}
/// <summary>
/// Initialize Application Context, include register application and register Crash Report.
/// </summary>
public void InitAdpApplication()
{
try
{
this._adpApplication = new com.intel.adp.AdpApplication(this._adpApplicationID, false);
this._adpApplication.SetCrashReport(new IadpCrashReport());
this._initCompleted = true;
}
catch (UnauthorizedException unauthorizedEx)
{
HandleSDKException(unauthorizedEx);
}
catch (InitializationException initEx)
{
HandleSDKException(initEx);
}
catch (AdpRuntimeException rtEx)
{
HandleSDKException(rtEx);
}
catch (AdpWarningException warnEx)
{
HandleSDKException(warnEx);
}
}
/// <summary>
/// Register customized Crash Report.
/// </summary>
/// <param name="CrashReport">Customized Crash Report object instance.</param>
/// <remarks>Your Crash Report class must inherit from IadpCrashReport class.</remarks>
public void RegisterCrashReport(IadpCrashReport CrashReport)
{
this._adpApplication.SetCrashReport(CrashReport);
}
/// <summary>
/// Run application.
/// </summary>
public void Run()
{
if (this._initCompleted)
Application.Run(this);
}
/// <summary>
/// Exit this application.
/// </summary>
public void Exit()
{
Application.Exit();
}
/// <summary>
/// Begin SDK event instrumentation.
/// </summary>
public void BeginEvent()
{
try
{
this._adpApplication.BeginEvent();
}
catch (UnauthorizedException unauthorizedEx)
{
HandleSDKException(unauthorizedEx);
}
catch (InitializationException initEx)
{
HandleSDKException(initEx);
}
catch (AdpRuntimeException rtEx)
{
HandleSDKException(rtEx);
}
catch (AdpWarningException warnEx)
{
HandleSDKException(warnEx);
}
}
/// <summary>
/// End SDK event instrumentation.
/// </summary>
public void EndEvent()
{
try
{
this._adpApplication.EndEvent();
}
catch (UnauthorizedException unauthorizedEx)
{
HandleSDKException(unauthorizedEx);
}
catch (InitializationException initEx)
{
HandleSDKException(initEx);
}
catch (AdpRuntimeException rtEx)
{
HandleSDKException(rtEx);
}
catch (AdpWarningException warnEx)
{
HandleSDKException(warnEx);
}
}
/// <summary>
/// Handling Application ID upgrade authorization.
/// </summary>
/// <param name="IdapCode0">Application ID Code Part 1.</param>
/// <param name="IdapCode1">Application ID Code Part 2.</param>
/// <param name="IdapCode2">Application ID Code Part 3.</param>
/// <param name="IdapCode3">Application ID Code Part 4.</param>
public void Upgrade(uint IdapCode0, uint IdapCode1, uint IdapCode2, uint IdapCode3)
{
try
{
this._adpApplication.Upgrade(new AdpApplicationId(IdapCode0, IdapCode1, IdapCode2, IdapCode3));
}
catch (UnauthorizedException unauthorizedEx)
{
HandleSDKException(unauthorizedEx);
}
catch (InitializationException initEx)
{
HandleSDKException(initEx);
}
catch (AdpRuntimeException rtEx)
{
HandleSDKException(rtEx);
}
catch (AdpWarningException warnEx)
{
HandleSDKException(warnEx);
}
}
private void HandleSDKException(AdpException SDKException)
{
IadpSDKException sdkException = null;
if (SDKException is UnauthorizedException)
{
sdkException = new IadpSDKException("SDK_APPID_UNAUTHORIZED_EXCEPTION", SDKException.Code, SDKException.Message);
if (this.UnauthorizedEvent != null)
this.UnauthorizedEvent(this, new IadpExceptionEventArgs(sdkException));
else
throw sdkException;
}
else if (SDKException is InitializationException)
{
sdkException = new IadpSDKException("SDK_INITIALIZE_EXCEPTION", SDKException.Code, SDKException.Message);
if (this.InitializationFailedEvent != null)
this.InitializationFailedEvent(this, new IadpExceptionEventArgs(sdkException));
else
throw sdkException;
}
else if (SDKException is AdpRuntimeException)
{
sdkException = new IadpSDKException("SDK_RUNTIME_EXCEPTION", SDKException.Code, SDKException.Message);
if (this.RuntimeErrorEvent != null)
this.RuntimeErrorEvent(this, new IadpExceptionEventArgs(sdkException));
else
throw sdkException;
}
else if (SDKException is AdpWarningException)
{
sdkException = new IadpSDKException("SDK_WARNING_EXCEPTION", SDKException.Code, SDKException.Message);
if (this.WarningErrorEvent != null)
this.WarningErrorEvent(this, new IadpExceptionEventArgs(sdkException));
else
throw sdkException;
}
else
{
sdkException = new IadpSDKException("SDK_UNKNOWN_EXCEPTION", ADP_RET_CODE.ADP_FAILURE, "Unknown SDK Exception");
throw sdkException;
}
}
}
Reference:
Intel AppUp SDK Developer's Guide.