WCF & IoC & DI Improvements for V2.0

Coordinator
Jul 4, 2011 at 3:25 PM

We received feedback regarding our initial Dependency Injection and Unity IoC container implementation.

Feedback 1:

First, in our V1.0 we were abstracting our IoC Container (IContainer) which we were doing in a similar way than Microsoft P&P with ‘Common Service Locator’: http://commonservicelocator.codeplex.com/

But we acknowledge that it is not really necessary for a standalone application. For instance, P&P CommonServiceLocator was especially made for frameworks/libraries integration more than for a standalone application. Also, if you stick Unity to a common interface, you won’t be able to use Unity for advanced scenarios like Calls-Interception it you want to make kind of AOP, etc. Therefore, for V2.0 we decided to eliminate that abstraction, using Unity directly.

Feedback 2:

Unity integration with WCF can be improved.

When talking about DI (Dependency Injection) and as we state in our guidance, it is important that the dependencies objects graph must be started from the initial entry point to your Application Server (either WCF or ASP.NET MVC). You should not use container.Resolve() in any layer. Ok, we were doing that, as the only layer when we had container.Resolve() was at the WCF Service Layer. Then, from the WCF methods, the DI objects graph was created down to all dependencies like Application Services, Domain Services, Repositories, Unit of Work, etc.

So, we were doing DI (not ServiceLocator pattern), in this way, starting on each WCF Service method:

WCF Service methods (Initially):

public List<CustomerListDTO> FindCustomersInPage(int pageIndex, int pageCount)
{

   //Starting point for this DI Object graph
   ICustomerAppService customerService = Container.Current.Resolve<ICustomerAppService>();
  return customerService.FindCustomers(pageIndex, pageCount);
}

 

This way, we are putting “container.resolve()” sentences only in one layer, the initial layer (WCF Service) and we chose to leave it like that because it is quite easy to understand for anybody even with few WCF and IoC/DI/Unity knowledge. But still, we would have at least one call to the Unity container per WCF-Service method, like I mentioned.

On the other hand, we acknowledge that this approach is improvable because it would be much better if we could have a deeper integration with WCF. I mean, instead of starting on the WCF methods (kind of a second WCF level), the Dependency Injection should start with the WCF-Service class and constructor themselves. Doing so, we could have a single line of code calling the Unity container for the whole solution. Dependency Injection should start from the WCF Service class Inception. :-)

This better approach is going to be initially more complex to understand (just a little), but it is worth to do it and ultimately, our application code and WCF Services will be even thiner (as single line of code for each WCF Service method).

The approach we have chosen is based on a WCF Extensibility point that WCF has which is the IInstanceProvider interface. Creating a custom InstanceProvider that implements that interface is probably the best way to integrate our IoC container instances creation with WCF Services.

This is our UnityInstanceProvider class which will be invoked automatically by WCF:

    public class UnityInstanceProvider : IInstanceProvider
    {
        Type _serviceType;
        IUnityContainer _container;

 

        public UnityInstanceProvider(Type serviceType)
        {
            if (serviceType == null)
                throw new ArgumentNullException("serviceType");

            this._serviceType = serviceType;
            _container = Container.Current;
        }
        
        public object GetInstance(InstanceContext instanceContext, 

                                                 System.ServiceModel.Channels.Message message)
        {
            
//This is the only call to UNITY container in the whole solution
            return _container.Resolve(_serviceType);

        }
        

        public object GetInstance(InstanceContext instanceContext)
        {
            return GetInstance(instanceContext, null);
        }
        
        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
            if (instance is IDisposable)
                ((IDisposable)instance).Dispose();
        }
    }

 

After having our custom InstanceProvider we need a way to tell WCF that we want him to invoke our InstanceProvider. The way to do that in WCF is using WCF-Behaviors.

So we have created a WCF-Behavior called ‘UnityInstanceProviderServiceBehavior’. We also created it as an Attribute, so we can easily apply it to our WCF Service:

    public class UnityInstanceProviderServiceBehavior : AttributeIServiceBehavior
    {        
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 

                                                                           ServiceHostBase serviceHostBase)
        {
            foreach (var item in serviceHostBase.ChannelDispatchers)
            {
                var dispatcher = item as ChannelDispatcher;
                if (dispatcher != null// add new instance provider for each end point dispatcher
                {
                    dispatcher.Endpoints.ToList().ForEach(endpoint =>
                    {
                        endpoint.DispatchRuntime.InstanceProvider = 

                                         new UnityInstanceProvider(serviceDescription.ServiceType);
                    });
                }
            }            
        }

        //Other ommitted methods…

    }

Then, we simple decorate our WCF Service classes with our behavior, in a similar way we are applying our exception handling attribute, like the following:

[ApplicationErrorHandlerAttribute()] // manage all unhandled exceptions
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
[UnityInstanceProviderServiceBehavior()] 
//create instance and inject dependencies using unity container
public class ERPModuleService : IERPModuleService
{  
     //Dependencies aggregating several Application Layer Services of this MODULE

     ICustomerAppService _customerAppService;
     ISalesAppService _salesAppService;

      //WCF Class Constructor where we specify our DEPENDENCIES

      public ERPModuleService(ICustomerAppService customerAppService,

                                                  ISalesAppService salesAppService)
    {
        //… Validations ommitted…

       // Keep dependencies’ objects graphs created by the Unity Container
            _customerAppService = customerAppService;
            _salesAppService = salesAppService;
    }

   //A single line of code per WCF Service Method 
   //(Errors handling and instances creation are based on WCF behaviours attributes )
   public List<CustomerListDTO> FindCustomersByFilter(string filter)
   {
      return _customerAppService.FindCustomers(filter);
    }

 

   //Other WCF Service methods

   //…

}

 

Now, as you can see, our WCF-Services are the simplest, one line of code!. I guess this cannot be thinner… ;-)

These changes are already updated within the CODEPLEX Source-control. You can do a ‘Get Latest Version’ if you want to check it out running the whole app.

Comments/Feedback about this improvement?

We’d really appreciate your constructive feedback in order to improve any area of this current ALPHA version. J

Thanks,

Cesar.

Jul 21, 2011 at 8:36 AM

But why Ioc Container is only in Distributed Service Layer? You needed only is that layer? And for testing purpose? Why not to put it in Crosscutting layer like previously (but clearly without abstraction?

Thanks.

 

Jul 21, 2011 at 3:58 PM

Creo que estoy un poco de acuerdo con lo que sugiere mojo2, es decir, tanto para  la inicialización ded  IoC container, como asi también el nuevo manejo de excepciones propuesto, están implementados dentro de la capa se servicios distribuidos.

Por un lado estariamos incluyendo logica de infrastructura en esta capa, y por otro lado, en caso de tener clientes que no utilicen esta capa deberíamos reimplementar en otro lugar (y por lo tanto duplicar) el manejo de IoC y de las excepeciones.

Gracias.

Coordinator
Jul 21, 2011 at 5:32 PM

@ mojo2: Dependency Injection has to start at your Server's entry point. In this case, our entry point is WCF Services. But then, the Dependencies injection will be applied through all layers based on constructors injection. So we are using Dependency Injection in all layers, not only in the Distributed Services layer.

@muzzomar:

Crosscutting concerns are mainly seedwork/framework you can re-use in every layer and in several Bounded-Contexts or even several projects.

If we put our container (and types registration) within the Crosscutting concerns, that won't be a crosscutting point for any Bounded-Context because we are registering specific types/classes for a sepecifc Bounded-Context.

The only option that we could do is that we could make a sub-layer within the Crosscutting concerns specifically made for each Bounded-Context and then we could put there the container registration. But then, we can have problems with circular references..

In any case, we'll think about it. We discussed this very same point a few weeks ago, and we might change this when adding another server entry point, like ASP.NET MVC. Then it makes sense trying to have a single container shared for both entry points (WCF and ASP.NET MVC).

Thanks for the feedback! :-)

Cesar.

Jul 13, 2012 at 1:30 PM

Hi Cesar, first and foremost, I wanna thank you and your team for all your effort in order to bring your knowledge for all the software development world.

I will take advantage of this thread to say that we do really need a clever and neat way to manage containers and dependency throughout different Bounded Context when not having a Distributed Services Layer, but I already know you are working on it.

On the other hand, I think I speak for so may developers when I say that there is a need of seeing a code example, even a tinny one, regarding to how to implement a relationship between two Bounded Context. I've seen the theory about Shared Kernel, Customer/Supplier, and so on; but when I go to forums and threads about it, I encounter a common huge doubt about it. I've come up with a possible trick of implementing abstract classes in the Shared Kernel for the common types and then inherit from them in the implicated BC using entity framework TPH to map to the DB but I don't really sure if it's a good practice. I'll appreciate so much any clue or thought on that.

Thanks in advance, and regards,

Eric.

Coordinator
Jul 13, 2012 at 3:12 PM

Hi Eric,

Regarding handling several BCs, you can see a nice example from Microsoft P&P in the "CQRS Journey" Project and its sample application. Even when it is CQRS (a special case/approach within DDD), we implemented several BCs, even a plain CRUD BC in order to show how to integrate several BCs, complex (CQRS/DDD) and simple (CRUD) BCs.

Basically, it is based on async events, and in most of the cases you will have a different MODEL per BC where you can have the same entity concept with different attibutes.

Take a look to:

https://github.com/mspnp

You have the simple App and also a Guidance documentation, similar to the approach we made with NLayerApp.

Aug 8, 2012 at 12:47 PM

Hi Cesar,

here is another one, trying to implement communication between BCs ;)

Basically I have made initial research (including mspnp), but for tha fundamental question I cannot find suitable answer. We decided to use NServiceBus for BC communication but my question is who is subscribing and publising events in the DDD. Are these domain entities, domain services, application services or all of them? Furthermore, BC should be independent and this requirement  is violated when first BC is subscribing to events of secound BC. What is your take on this?

Kind regards,

mat3y 

 

Coordinator
Aug 10, 2012 at 5:11 AM

Hi mat3y,

BC should be independent us much as possible, but for sure, they may have certain dependencies. Then you should communicated them asynchronously based on events. It is quite similar to the CQRS's system, so, the objects who should generate events are the ones who update the DB, therefore, those objects are the Repositories. Just after writing on the database they should generate an event and publish it to a Bus (whether it is a simple bus, in memory, queues or a mor ecomplex service bus like NServiceBus or Windows Azure Service Bus).

Then, any other component who is subscribed to those event will get the events and will have to process them. Those components are called EVENT-HANDLERS.

If you understand how CQRS works you will understand how to communicate different BCs.

Btw, the Microsoft P&P CQRS Project is an example of communicating different BCs. :-)

Cesar.