0
votes

I am building a POC that aims to demonstrate how a dependency hierarchy can be constructed from within a WCF service with Unity and keep all assemblies in an application completely loosely coupled.

What I did is to create the following class libraries:

Data Access Layer:
- One assembly with the repository interface.
- One assembly with the implementation of this interface that pretends to access a DB.
- One assembly with the implementation of this interface that pretends to access XML docs.

Business Layer:
- One assembly with the business object interface.
- One assembly with the implementation of this interface that receives on its constructor the repository interface.

Service Layer:
- One assembly with the service interface.
- One assembly with the implementation of this interface that receives on its constructor the business object interface.

Finally I created an assembly with a Service Host Factory, a Service Host, and an Instance Provider that will be in charge of creating the dependency hierarchy. The code looks like so:

public class UnityServiceHostFactory : ServiceHostFactory
{
    private readonly UnityContainer _container;

    public UnityServiceHostFactory()
    {
        _container = new UnityContainer();

        new ContainerConfigurator().Configure(_container);
    }

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return new UnityServiceHost(_container, serviceType, baseAddresses);
    }
}

public class ContainerConfigurator
{
    public void Configure(UnityContainer container)
    {
        container.RegisterType<IInvoiceRepository, InvoiceRepository>("dbInvoiceRepository");
        container.RegisterType<IInvoiceRepository, XmlInvoice>("xmlInvoiceRepository");
        container.RegisterType<IInvoiceFinder, InvoiceFinder>();
    }
}

public class UnityServiceHost : ServiceHost
{
    public UnityServiceHost(UnityContainer container, Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses)
    {
        if(container == null) throw new ArgumentNullException("container");

        var contracts = ImplementedContracts.Values;

        foreach (var c in contracts)
        {
            var instanceProvider = new UnityInstanceProvider(container, serviceType);

            c.Behaviors.Add(instanceProvider);
        }
    }
}

public class UnityInstanceProvider : IInstanceProvider, IContractBehavior
{
    private readonly UnityContainer _container;
    private readonly Type _serviceType;

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

        _container = container;
        _serviceType = serviceType;
    }

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

    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        return _container.Resolve(_serviceType);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
        _container.Teardown(instance);
    }

    public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
    {
    }

    public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
    {
        dispatchRuntime.InstanceProvider = this;
    }

    public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
    }

    public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }
}

I am testing this with a console application, I instantiate the service proxy and make the call to its method but, since both registrations are named Unity does not know which one to instantiate. If I remove the name from either of them it gets resolved successfully.

Basically I would like to be able to do something like this:

static void Main(string[] args)
    {
        //First call, want it to resolve to the InvoiceRepository concrete type
        //new InvoiceService(new InvoiceFinder(new InvoiceRepository))
        var invoiceService1 = new InvoiceProxy();
        var response1 = invoiceService1.GetSumarizedInvoiceBy(new InvoiceRequest(1));


        //Second call, want it to resolve to the XmlInvoice concrete type
        //new InvoiceService(new InvoiceFinder(new XmlInvoice))
        var invoiceService2 = new InvoiceProxy();
        var response2 = invoiceService2.GetSumarizedInvoiceBy(new InvoiceRequest(2));
    }

Notice how invoiceService1 and invoiceService2 are two different instances of the same service but the dependency within its own dependency was resolved differently for both.

What do I have to do so that I can tell Unity which repository to instantiate when I am either instantiating the service proxy or calling its method?

Thanks for your help.

1

1 Answers

0
votes

Pass the name you gave Unity in the RegisterType<>() call to Resolve<>().

From Resolving an Object by Type and Registration Name

// Create container and register types
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType(typeof(MyServiceBase), typeof(DataService), "Data");
myContainer.RegisterType(typeof(MyServiceBase), typeof(LoggingService), "Logging");

// Retrieve an instance of each type
MyServiceBase myDataService = (MyServiceBase)myContainer.Resolve(typeof(MyServiceBase), "Data");

You are using the generic extension methods that are equivalent to this example.