Services and Injection
Posted by: laurentl in RolePadService on
Jan 17, 2009
Today I'd like to discuss a bit about the services.
A service is basically just a class that can be used for two different puposes.
The most common is to share an instance of a class with different Tasklets / request document handlers / other services.
The other use is to have a class (most likely starting a background thread) to do some processing in the background.
There are a few services that are included in the framework that you might want to use (ILoggingService, IConnectionMonitor, BarcodeScanningService...).
Services also have scopes. It defines whether to share the instance of the class with the whole application, all tasklets of a specific orchestration or just create a new one for each tasklets.
So first, let's start with the most common use: sharing a class through the whole application.
Let's take for instance, the ILoggingService that is defined as a global service (the default scope when not defined in the app.config). In that case, the service is defined as an interface so that if you want to change its implementation, you can replace some line in the app.config (I'll come to that in a later post) and all components using this interface as service will use your implementation.
So if from you Tasklet you need to create a log (it can be to track a crash, to send custom information to the logging console...) then you have to define in your class this line:
[RolePadService]public ILoggingService LoggingService { get; set; }
Then you can submit a log from your code : LoggingService.Submit(new LogEntry("Enduser used my tasklet! :)"));
The RolePadService attribute will "trigger" the framework to create a new instance of the class defined in the app.config that implement the ILoggingService if nobody else has requested it before (it also depends on the scope but for this service we assume that the scope is set to Global).
This injection is done only for classes that are created by the framework, so for classes extending Tasklet, RequestDocumentHandler and services. There is also a way to inject services to your custom classes using the IServiceFactory service (I'll try to cover that in another post). The common "mistake" is to define services on other type of classes and expect the service to be injected.
When services are defined as interfaces in your components, the framework has to know how to create them, therefore they have to be defined in the app.config in the service section otherwise the application will crash as it doesn't know what class to create.
The injection flow works that way : the framework first creates the Tasklet / request document handler / service and then will parse the class to see if it contains any property with the RolePadService attribute in which case, it will create them and set them on the component instance. That means that you should never use the services in the constructor of your classes.
For the request document handlers it is a bit different, as they are being created by the framework without being part of an orchestration, you can only request services with global scope.
Another example of a service but used this time with an orchestration scope is the IBasketService from the mobile sales.
This service has in the app.config Orchestration as scope so that everytime a new order orchestration is started, a new instance of the basket is used. When the orchestration is closed, the class is then disposed if it implements the IDisposable interface.
The RequestManager Class is an example of a use of a "background" service. This service has the startup attribute set to true meaning that while the splash screen is displaying "Setting up services..." the service is instanciated.
The RequestManager service is starting a background thread that will submit new documents coming to the queue.
You could imagine a background service reacting on an incoming sms to do a specific action related to the application.
Thats it for this time. I'll try to explain next time about all different configuration cases.
