使用应用程序扩展服务可以扩展 Silverlight 应用程序模型。通常使用扩展服务来封装特定功能域中由多个应用程序使用的功能。例如,可以使用扩展服务来实现专用媒体处理或自定义数据访问层。
Application 类提供多数应用程序共用的服务。有关更多信息,请参见应用程序服务。可以通过创建自定义 Application 子类来提供附加服务,但这可能会带来不必要的复杂性。例如,创建子类将要求应用程序派生自您的子类,这会妨碍同时使用多个扩展框架。
取代创建自定义 Application 子类的方法是通过 Application..::.ApplicationLifetimeObjects 属性添加应用程序扩展服务。这使您能够组合多个服务并实现复杂的服务依赖项。
应用程序扩展服务必须实现 IApplicationService 接口。此接口对服务初始化和清除提供支持。如果服务需要与应用程序生存期事件进行更深入的集成,则还可以实现 IApplicationLifetimeAware 接口。
本主题包含以下各节:
注册扩展服务
通过将应用程序扩展服务添加到 Application..::.ApplicationLifetimeObjects 列表可以注册这些服务。可以在应用程序 XAML 或程序代码中(或者同时使用)完成此操作。
服务以您指定的顺序进行注册。这使您能够创建对之前注册的服务具有依赖项的服务。
必须在应用程序构造函数中执行服务注册。如果在应用程序 XAML 中指定服务,则会在构造函数加载 XAML 时,通过调用生成的 InitializeComponent 方法注册这些服务。
下面的代码示例演示如何在 App.xaml 文件中注册两个服务。此代码假定您已定义一个名为 svc 的 XML 命名空间,该命名空间引用包含服务类的命名空间和程序集。
复制代码
下面的代码示例演示如何使用应用程序构造函数中的程序代码注册相同的服务。
[C#]
复制代码
this.ApplicationLifetimeObjects.Add( new SilverlightApplicationService.ApplicationService1());
this.ApplicationLifetimeObjects.Add(
new SilverlightApplicationService.ApplicationService2());
您的服务类可以实现可在 XAML 中设置或在服务构造函数中初始化的属性。默认构造函数是使用 XAML 注册服务所必需的。因此,如果实现带有参数的构造函数,则还应显式实现无参数构造函数。
从应用程序代码访问扩展服务
可以从 ApplicationLifetimeObjects 列表检索已注册的服务对象。但是,此列表要求使用整数索引,而当您添加、移除或重新排序服务时,特定服务的索引将发生更改。因此,应在您的服务实现中提供其他访问形式。
一种非常方便的模式是对服务类实现一个静态 Current 属性。可以在服务初始化代码中设置此属性。这使得更易于在要注册的任何附加服务的应用程序代码和初始化代码中访问实例。
下面的代码示例演示如何通过 Current 属性访问服务实例,然后访问该服务的一个实例属性。
[C#]
复制代码
ApplicationService1 service1 = ApplicationService1.Current;String param1 = service1.InitParams["param1"];
下节包含实现和初始化这些属性的代码示例。
实现 IApplicationService 接口
Silverlight 应用程序扩展服务必须实现 IApplicationService 接口。此接口定义两个方法:StartService 和 StopService。
通常实现 StartService 方法来初始化服务并获取所有必需的非托管资源。
在 Application..::.Startup 事件之前,应用程序会按服务的注册顺序为每个服务调用 StartService 方法。这使每个服务都可用于在注册顺序中位于其后的各服务的 StartService 方法。此外,所有服务都可供 Startup 事件处理程序使用。
StartService 方法具有类型为 ApplicationServiceContext 的单个参数。此类型公开 ApplicationInitParams 属性,提供对宿主 HTML 中指定的 InitParams 值的访问。
下面的代码示例演示 StartService 方法的实现,该实现初始化一个静态 Current 属性,并将初始化参数存储到一个实例属性中。
[C#]
复制代码
public static ApplicationService1 Current { get; set; }private Dictionary
InitParams { get; set; }
public void StartService(ApplicationServiceContext context)
{
Current = this;
InitParams = context.ApplicationInitParams;
}
通常实现 StopService 方法来关闭应用程序并释放所有非托管资源。
在 Application..::.Exit 事件之后,应用程序会按注册服务的相反顺序为每个服务调用 StopService 方法。所有服务仍可供应用程序的 Exit 事件处理程序使用。此外,每个 StopService 方法仍可访问在注册顺序中位于其前的所有服务。
实现 IApplicationLifetimeAware 接口
IApplicationLifetimeAware 接口继承 IApplicationService 接口,并定义用于处理以下四个附加应用程序生存期事件的方法:
顾名思义,这些方法在紧接应用程序的 Startup 和 Exit 事件之前和之后调用。
通常为对其他服务或应用程序代码具有复杂依赖项的服务实现 IApplicationLifetimeAware 接口。例如,某个服务的 Starting 方法可以访问其他所有已注册的服务,而不考虑注册顺序。此外,Started 方法可以访问应用程序 Startup 事件中初始化的所有内容,如 RootVisual 属性值。
下面的列表指示发生应用程序生存期事件以及调用 IApplicationService 和 IApplicationLifetimeAware 方法的顺序:
- 应用程序为每个应用程序服务调用 IApplicationService..::.StartService 方法。
- 应用程序为每个 IApplicationLifetimeAware 服务调用 Starting 方法。
- 发生 Application..::.Startup 事件。
- 应用程序为每个 IApplicationLifetimeAware 服务调用 Started 方法。
- 应用程序一直运行,直到由用户操作启动停止序列。这通常在用户关闭应用程序或浏览器窗口时或者用户将浏览器导航到新网页时发生。
- 应用程序为每个 IApplicationLifetimeAware 服务调用 Exiting 方法。
- 发生 Application..::.Exit 事件。
- 应用程序为每个 IApplicationLifetimeAware 服务调用 Exited 方法。
- 应用程序为每个应用程序服务调用 IApplicationService..::.StopService 方法。
应用程序为每个服务调用每个服务方法一次。这些方法按这些服务的注册顺序调用,但 StopService 方法按相反顺序调用。这样就可以如上一节所述按顺序清除。