0

我正在构建一个 POC,旨在演示如何使用 Unity 从 WCF 服务中构建依赖层次结构,并使应用程序中的所有程序集完全松散耦合。

我所做的是创建以下类库:

数据访问层:
- 一个带有存储库接口的程序集。
- 一个实现了这个接口的程序集,它假装访问一个数据库。
- 一个实现了这个接口的程序集,它假装访问 XML 文档。

业务层:
- 一个带有业务对象接口的程序集。
- 一个实现了此接口的程序集,它在其构造函数中接收存储库接口。

服务层:
- 一个带有服务接口的组件。
- 一个实现了此接口的程序集,它在其构造函数上接收业务对象接口。

最后,我创建了一个包含服务主机工厂、服务主机和实例提供程序的程序集,它将负责创建依赖关系层次结构。代码如下所示:

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)
    {
    }
}

我正在使用控制台应用程序对此进行测试,我实例化了服务代理并调用了它的方法,但是由于两个注册都被命名为 Unity 不知道要实例化哪一个。如果我从其中任何一个中删除名称,它将成功解决。

基本上我希望能够做这样的事情:

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));
    }

请注意 invoiceService1 和 invoiceService2 如何是同一服务的两个不同实例,但其自身依赖项中的依赖项对两者的解析方式不同。

当我实例化服务代理或调用其方法时,我必须做什么才能告诉 Unity 要实例化哪个存储库?

谢谢你的帮助。

4

1 回答 1

0

将您在 RegisterType<>() 调用中为 Unity 提供的名称传递给 Resolve<>()。

通过类型和注册名称解析对象

// 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");

您正在使用与此示例等效的通用扩展方法。

于 2013-03-21T20:17:49.937 回答