by codeblock via Silverlight & XAML Playground on 2/6/2011 10:33:47 PM
For an example I'm writing for my next presentation at the end of February, I’m trying to build an application skeleton that have lot of extensibility points and my goal is to make almost everything pluggable. An interesting thing I did today is to inject in the application a number of ApplicationServices. The application services are an useful tool to have application-wide services available during the entire lifetime, and they are very easy to create and install. First of all you have to implement the IApplicationService interface and if you want a more detailed control on application lifecycle you can also implement the IApplicationLifetimeAware interface. These interfaces give you a number of methods that notify when the application is started of stopped. Here is an example of a service and its installation:
1: public class SampleService : IApplicationService
2: {
3: public static SampleService Current { get; private set; }
4:
5: /// <summary>
6: /// Initializes a new instance of the <see cref="ServiceHost"/> class.
7: /// </summary>
8: public SampleService()
9: {
10: if (SampleService.Current != null)
11: throw new InvalidOperationException("Service already exists");
12:
13: SampleService.Current = this;
14: }
15:
16: /// <summary>
17: /// Called by an application in order to initialize the application extension service.
18: /// </summary>
19: /// <param name="context">Provides information about the application state.</param>
20: public void StartService(ApplicationServiceContext context)
21: {
22: // initialize here the service
23: }
24:
25: /// <summary>
26: /// Called by an application in order to stop the application extension service.
27: /// </summary>
28: public void StopService()
29: {
30: // release resources here
31: }
32: }
33:
34: // -----------
35:
36: <Application.ApplicationLifetimeObjects>
37: <local:SampleService />
38: </Application.ApplicationLifetimeObjects>
Today I've asked myself how can I inject an application service with MEF. If I have many modules I plug to my skeleton, let say they are customization for different customers, I suppose I can also have one or more application services injected by these modules for the purpose of the customization. To solve this pluggability problem I’ve created a simple HostService that implement both IApplicationService and IApplicationLifetimeAware, then I added a property, imported with MEF, that is a collection of IApplicationService. So when I load the ApplicationService in the App.xaml the constructor perform the Composition and I have a bunch of services loaded into the host service.
1: public class HostService : IApplicationService, IApplicationLifetimeAware
3: public static HostService Current { get; private set; }
6: /// Gets or sets the services.
8: /// <value>The services.</value>
9: [ImportMany]
10: public IEnumerable<IApplicationService> Services { get; set; }
11:
12: /// <summary>
13: /// Initializes a new instance of the <see cref="ServiceHost"/> class.
14: /// </summary>
15: public HostService()
16: {
17: if (HostService.Current != null)
18: throw new InvalidOperationException("Service already exists");
19:
20: HostService.Current = this;
21: CompositionInitializer.SatisfyImports(this);
22: }
23:
24: /// <summary>
25: /// Called by an application immediately after the <see cref="E:System.Windows.Application.Exit"/> event occurs.
26: /// </summary>
27: public void Exited()
28: {
29: foreach (IApplicationLifetimeAware service in this.Services.OfType<IApplicationLifetimeAware>())
30: service.Exited();
32:
33: /// <summary>
34: /// Called by an application immediately before the <see cref="E:System.Windows.Application.Exit"/> event occurs.
35: /// </summary>
36: public void Exiting()
37: {
38: foreach (IApplicationLifetimeAware service in this.Services.OfType<IApplicationLifetimeAware>())
39: service.Exiting();
40: }
41:
42: /// <summary>
43: /// Called by an application immediately after the <see cref="E:System.Windows.Application.Startup"/> event occurs.
44: /// </summary>
45: public void Started()
46: {
47: foreach (IApplicationLifetimeAware service in this.Services.OfType<IApplicationLifetimeAware>())
48: service.Started();
49: }
50:
51: /// <summary>
52: /// Called by an application immediately before the <see cref="E:System.Windows.Application.Startup"/> event occurs.
53: /// </summary>
54: public void Starting()
55: {
56: foreach (IApplicationLifetimeAware service in this.Services.OfType<IApplicationLifetimeAware>())
57: service.Starting();
58: }
59:
60: /// <summary>
61: /// Called by an application in order to initialize the application extension service.
62: /// </summary>
63: /// <param name="context">Provides information about the application state.</param>
64: public void StartService(ApplicationServiceContext context)
65: {
66: foreach (IApplicationService service in this.Services)
67: service.StartService(context);
68: }
69:
70: /// <summary>
71: /// Called by an application in order to stop the application extension service.
72: /// </summary>
73: public void StopService()
74: {
75: foreach (IApplicationService service in this.Services)
76: service.StopService();
77: }
78: }
As you can see in the code, for every method exposed by the interfaces I make a loop and call the corresponding method on each service. The services have to be exported ad IApplicationService, but if they implements also the other interface the host call the relative methods. To export a service you can simple decorate it with an Export attribute.
1: [Export(typeof(IApplicationService))]
2: public SampleService : IApplicationService
3: {
4: // implement the service
5: }
Once installed, this very simple service let you easily inject new services without the need of recompile the software. Simply add the assembly where it resides to the catalog and the services will be installed seamless.
Magic…
Original Post: Inject Application Services using MEF
The content of the postings is owned by the respective author. Silverlight Feeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on Silverlight Feeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.