LA.NET [EN]

May 08

The S#arp framework: WCF integration

Posted in S#arp      Comments Off on The S#arp framework: WCF integration

Today we’re going to take a look at the SharpArch.Wcf assembly, which contains several classes that will help use the S#arp framework from within you WCF services. If you’re looking at the source code, you’ll surely notice that it has lots of  classes, many of each are there just for supporting infrastructural WCF code.

We’ll start by looking at the WcfSessionStorage class. This class implements the ISessionStorage interface we’ve met a in a previous post and it relies on the SessionInstanceExtension type for providing the storage used for keeping a valid ISession instance during a request. This type (SessionInstanceExtension) is really simple: it implements the IExtension<T> interface and adds a public read/writer property of type ISession that will  be filled with a valid session for each request.

The SessionInstanceExtension is injected in the “current” context through the custom InstanceCreationInitializer type, which implements the IInstanceContextInitializer interface (you can implement this interface if you’re interested in influencing the resulting InstanceContext that will be used in the current request). It implements the initialize method by adding an instance of type SessionInstanceExtension to the current context’s extensions  collection.

The ISession lifetime is “controlled” (sort of!)  by a custom IDipatchMessageInspector type (DispatchMessageInspector). The AfterMessageinspector is simple: it will just return the current session (NHibernateSession.Current – recall that this feature relies on the WcfSessionStorage  we’ve talked about in the previous paragraph and it will automatically set it up when it’s null). The AfterReceiveRequest is responsible for doing the clean up: if it finds a valid session, it will close it and remove it from the storage (ie, it will set it to null).

This assembly will also add a custom IInstanceProvider type, ServiceLocatorInstanceProvider, which relies on the  ServiceLocator for getting a reference to the service that will handle the current request.

Injecting all these “pieces” is the responsibility of the custom ServiceHost class (that expands the WCF’s ServiceHost type). If you look at the code, you’ll see that it overrides the OnOpening method for adding a custom service behaviour:

protected override void OnOpening() {
            Description.Behaviors.Add(new ServiceBehavior());
            base.OnOpening();
}

ServiceBehaviour will go over each endpoint you’ve set up and it will:

  • set the instance provider to a new instance of type ServiceLocatorInstanceProvider;
  • add the InstanceCreationInitializer to the instance context initializers collection;
  • add the DispatchMessageInspector type to the message inspectors collection.

The only missing peace is the injection of the custom ServiceHost: it’s done through a factory called ServiceHostFactor. The method will expand the ServiceHostFactory and override the CreateServiceHost method in order to return an instance of our custom ServiceHost type.

Now that we understand the infrastructure, we only need to know how to use it. To show what is need, we’re going to take a look at the Northwind sample. As you might expect after the previous description,the only thing we need to do is configure our service so that it is created through our custom service host (which means that we want to replace the default service host factory with the one introduced by the SharpArch.Wcf assembly). This is really easy and you can do it by setting the Factory attribute on the ServiceHost directive:

<%@ ServiceHost Language="C#" Debug="true"
    Service="Northwind.Wcf.TerritoriesWcfService"
    Factory="SharpArch.Wcf.NHibernate.ServiceHostFactory,SharpArch.Wcf" %>

btw, and in case you didn’t notice, the helper classes introduced in the current context by our custom service host allow us to create services without default constructors (notice that the instance provider depends on the ServiceLocator for performing the instantiation of the service). If you look at the TerritoriesWcfService, you’ll notice that it doesn’t have a default constructor:

public class TerritoriesWcfService : ITerritoriesWcfServic    {
        public TerritoriesWcfService(IRepository<Territory> territoryRepository) {
            Check.Require(territoryRepository != null, "territoryRepository may not be null");

            this.territoryRepository = territoryRepository;
        }
   //more code

I’m not sure about you, but I think I’ll really enjoy  this WCF integration stuff!

And that’s all for today. Keep tuned for more!