Archive

Archive for the ‘IoC’ Category

Dynamically adding RaisePropertyChanged to MVVM Light ViewModels using Microsoft Unity

July 28, 2011 3 comments

Introduction

In the past, I already wrote two articles about dynamically adding RaisePropertyChanged support to view models. Today, I will explain how this can be accomplished with the IoC container: Microsoft Unity. Unity has out of the box support for AOP. Using Unity is much easier than my two previous do-it-yourselves ways. For real applications, I recommend using Unity or similar frameworks!

Like in my previous articles, I want to write view models using the following code pattern:

[RaisePropertyChanged]
public virtual string SomeProperty { get; set; }

Instead of the standard pattern:

private string someProperty;

public string SomeProperty
{
    get
    {
        return someProperty;
    }
    set
    {
        someProperty = value;
        RaisePropertyChanged("SomeProperty");
    }
}

Implementation

In order to get started, the first thing we have to do is install both Unity and MVVM Light. To do this, I recommend using Nuget. In the official Nuget repository, Unity is split into two packages. For the AOP support, both packages need to be added to the Visual Studio project.

nuget_Unity

Now that we have all the required libraries, we can start coding. First, lets define our RaisePropertyChangedAttribute class.

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class RaisePropertyChangedAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new RaisePropertyChangedCallHandler();
    }
}

Because we want Unity to intercept calls, we must extend our attribute from HandlerAttribute. A custom HandlerAttribute must create and return a custom ICallHandler instance. We will return an instance of our custom RaisePropertyChangedCallHandler that we will create next.

Before writing our ICallHander, we must first look at the MSIL code generated by the C# compiler in order to understand .Net properties better. When a property is defined, 2 hidden methods are automatically created by the compiler; a get method and a set method. These methods have by default the name get_<property name> and set_<property name>.

Ildasm_property

With this knowledge in mind, the custom ICallHandler implementation is straightforward. We ask Unity to call the original set method and after its invocation we extract the name of property out of the name of the set method and we invoke the RaisePropertyChanged method of MVVM Light using reflection.

class RaisePropertyChangedCallHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        IMethodReturn methodReturn = getNext()(input, getNext);

        string propertyName = input.MethodBase.Name.Substring(4);

        MethodInfo raisePropertyChangedMethod = input.Target.GetType().GetMethod("RaisePropertyChanged",
            BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] {typeof(string)}, null);
        raisePropertyChangedMethod.Invoke(input.Target, new object[] { propertyName });

        return methodReturn;
    }

    public int Order { get; set; }
}

Configuring Unity

All that now remains is configuring Unity for our view model and activating virtual method AOP support for it. In code, we can define this using the following code sample:

IUnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterType<SampleViewModel>().
    Configure<Interception>().
    SetInterceptorFor<SampleViewModel>(new VirtualMethodInterceptor());

If we now use Unity for creating instances of our sample view model class, all the properties annotated with “RaisePropertyChanged” will atomically be “property change”-aware.

SampleViewModel vm = container.Resolve<SampleViewModel>();

Please note: This will not work in Silverlight, because of limitations in its runtime. (Silverlight does not allow the invocation of private methods using reflection for security reasons)

Categories: C#, IoC, MVVM, WPF Tags: , , , ,

Using an IoC container to create WCF service instances

Introduction

Using dependency injection and an IoC container increase the robustness of an application. Dependency injection is a design pattern that decouples behavior from dependency resolution. Thus making it easier to replace the actual implementation of components by mocked implementations during unit tests. IoC containers are frameworks that help you resolve dependencies for your .Net classes. Various implementations exist: Microsoft Unity, Ninject, Spring.Net, …

By default WCF requires that service implementation classes have a parameterless constructor. The sole exception are self hosted singleton services. In that case, you could also pass the required instance to the constructor of your ServiceHost class.

Luckily for us, WCF is very extensible and it allows us to change the component that is responsible for creating service instances. This component is called the instance provider and implements an interface called IInstanceProvider. In this article, I will show you how to create a new implementation that uses Ninject, but you could also use the IoC container of preference.

Getting Ninject

First we need to add Ninject to our project. Because NuGet is so popular these days in the Microsoft world, lets use it. So right click on References in Visual Studio and chose “Add Library Package Reference” and then search for Ninject.

AddLibraryPackageReference

When you click “install”, NuGet will download and add all the required assemblies of Ninject to the Visual Studio project. It will not install them in the GAC.

Creating the InstanceProvider

When you create a custom InstanceProvider, all you have to do is implement the interface IInstanceProvider. The required code to use an IoC container is very straightforward. We pass the Ninject kernel and the service type to the instance provider constructor and use the Ninject kernel to create instances of the service when required.

public class NinjectInstanceProvider : IInstanceProvider
{
    private Type serviceType;
    private IKernel kernel;

    public NinjectInstanceProvider(IKernel kernel, Type serviceType)
    {
        this.kernel = kernel;
        this.serviceType = serviceType;
    }

    public object GetInstance(InstanceContext instanceContext)
    {
        return this.GetInstance(instanceContext, null);
    }

    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        // Create the instance with your IoC container of choice, here I use Ninject.
        return kernel.Get(this.serviceType);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
    }
}

Hooking into the WCF pipeline

Now that we have created our custom instance provider we have to inject it into the WCF pipeline. This can be done in code or in the web.config file. Personally I prefer the web.config, but that’s a matter of taste.

To add behaviors to a WCF service, you have to create a class that implements IServiceBehavior. WCF calls the method ApplyDispatchBehavior when its loading the service and before it will start accepting client requests. In this method we will inject our custom instance provider.

public class NinjectBehaviorAttribute : Attribute, IServiceBehavior
{
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
        Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        Type serviceType = serviceDescription.ServiceType;
        IInstanceProvider instanceProvider = new NinjectInstanceProvider(new StandardKernel(), serviceType);

        foreach(ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
            {
                DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
                dispatchRuntime.InstanceProvider = instanceProvider;
            }
        }
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }
}

If the service behavior class extends from .Net Attribute class; you can use it to annotate your service implementation. WCF is able to detect such service behaviors and it will load and attach them to the service.

[NinjectBehaviorAttribute]
public class HelloService : IHelloService
{
}

If you don’t want to add the service behavior in code, but instead in the web.config file, you have to implement a class that extends from BehaviorExtensionElement. Again, this is very easy to do:

public class NinjectBehaviorExtensionElement : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof (NinjectBehaviorAttribute); }
    }

    protected override object CreateBehavior()
    {
        return new NinjectBehaviorAttribute();
    }
}

Now we can configure WCF to use Ninject from the web.config:

<system.serviceModel>
  <services>
    <!-- A dummy WCF service ... -->
    <service name="WcfIoc.HelloService" behaviorConfiguration="HelloServiceBehavior">
      <endpoint address=""
                binding="wsHttpBinding"
                contract="WcfIoc.IHelloService" />
    </service>
  </services>

  <behaviors>
    <serviceBehaviors>
      <behavior name="HelloServiceBehavior">
        <!-- Add the Ninject behavior to the WCF service. -->
        <ninject />
      </behavior>
    </serviceBehaviors>
  </behaviors>

  <extensions>
    <behaviorExtensions>
      <!-- Add the Ninject behavior extension -->
      <add name="ninject"
            type="WcfIoc.NinjectBehaviorExtensionElement, WcfIoc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
  </extensions>
</system.serviceModel>

We are done Glimlach I think that everybody will agree that WCF is very powerful and configurable, yet at the same time its internals are very intuitive and easy to understand.

Categories: C#, IoC, Ninject, WCF