使用Unity IoC容器解析C#中的包装类

使用Unity IoC容器解析C#中的包装类,c#,unity-container,ioc-container,wrapper,C#,Unity Container,Ioc Container,Wrapper,我想对两个不同的实现使用Unity resolveIService,以利用包装类,相当于: IService service = new DispatcherService(new RealService(), Application.Current.Dispatcher); 其中,DispatcherService和RealService都实现了iSeries设备接口 我有一个库,其中包含一些具有异步操作的服务。此服务的简化形式如下所示: public interface IService

我想对两个不同的实现使用Unity resolve
IService
,以利用包装类,相当于:

 IService service = new DispatcherService(new RealService(), Application.Current.Dispatcher);
其中,
DispatcherService
RealService
都实现了
iSeries设备
接口

我有一个库,其中包含一些具有异步操作的服务。此服务的简化形式如下所示:

public interface IService
{
    IAsyncResult StartSomeOperation();
    event EventHandler<EventArgs> SomeOperationCompleted;
}
using System;
using System.Windows.Threading;

public class DispatcherService : IService
{
    private Dispatcher dispatcher;
    private IService wrappedService;

    public DispatcherService(IService wrappedService, Dispatcher dispatcher)
    {
        this.wrappedService = wrappedService;
        this.wrappedService.SomeOperationCompleted += this.OnWrappedOperationCompleted;
        this.dispatcher = dispatcher;
    }

    public IAsyncResult StartSomeOperation()
    {
        return this.wrappedService.StartSomeOperation();
    }

    public event EventHandler<EventArgs> SomeOperationCompleted;

    private void OnWrappedOperationCompleted(object sender, EventArgs e)
    {
        if (this.SomeOperationCompleted != null)
        {
            Action completedSynch = () => this.SomeOperationCompleted(sender, e);
            this.dispatcher.Invoke(completedSynch);
        }
    }
}
但是unity不喜欢我编写IService接口的两个不同实现。 这段代码失败得很厉害:

    UnityContainer container = new UnityContainer();
    container.RegisterInstance<Dispatcher>(Application.Current.Dispatcher);
    container.RegisterType<IService, RealService>();
    container.RegisterType<IService, DispatcherService>();

    IService created = container.Resolve<IService>();
但我不认为这是一个好主意,空接口很难看,而且不能很好地扩展

解决此对象树的方法是什么


更新: 根据Dzmitry Huba给出的答案,以下是一些示例代码:

添加对Microsoft.Practices.Unity.StaticFactory的引用

简单工作代码:

    UnityContainer container = new UnityContainer();

    container.AddNewExtension<StaticFactoryExtension>()
        .Configure<IStaticFactoryConfiguration>()
        .RegisterFactory<IService>(cont =>
                new DispatcherService(new RealService(), Application.Current.Dispatcher));
        
    IService created = container.Resolve<IService>();
UnityContainer container=newunitycontainer();
container.AddNewExtension()
.Configure()
.RegisterFactory(续=>
新的DispatcherService(新的RealService(),Application.Current.Dispatcher));
IService created=container.Resolve();
更完整的工作代码,更好地处理实际服务的潜在依赖关系,如IoC容器应:

    UnityContainer container = new UnityContainer();
    container.RegisterInstance<Dispatcher>(Application.Current.Dispatcher);
    container.RegisterType<IService, RealService>("Real");
    
    container.AddNewExtension<StaticFactoryExtension>()
        .Configure<IStaticFactoryConfiguration>()
        .RegisterFactory<IService>(cont =>
               new DispatcherService(
                       cont.Resolve<IService>("Real"),
                       cont.Resolve<Dispatcher>()));

    IService created = container.Resolve<IService>()
UnityContainer container=newunitycontainer();
container.RegisterInstance(Application.Current.Dispatcher);
container.RegisterType(“Real”);
container.AddNewExtension()
.Configure()
.RegisterFactory(续=>
新调度员服务(
继续解决(“真实”),
继续解析();
IService created=container.Resolve()
此外,考虑到工厂注册非常冗长,我将做不止一个,我提出了一个扩展方法:

public static class ContainerExtensions
{
    public static void RegisterFactory<T>(this IUnityContainer container, FactoryDelegate factoryDelegate)
    {
        container.AddNewExtension<StaticFactoryExtension>()
            .Configure<IStaticFactoryConfiguration>()
            .RegisterFactory<T>(factoryDelegate);
    }
}
公共静态类ContainerExtensions
{
公共静态无效注册表工厂(此IUnityContainer容器,FactoryDelegate FactoryDelegate)
{
container.AddNewExtension()
.Configure()
.注册工厂(工厂代表);
}
}

您可以使用接受基于字符串的名称的RegisterType重载。在这种情况下,您将执行以下操作:

container.RegisterType<IService, RealService>("real");
container.RegisterType<IService, DispatcherService>("dispatcher");
这将允许您避免标记接口,这在大多数情况下不是一个好主意


但是,如果您希望保持代码干净,不受Unity的影响(如DependencyAttribute),并且在大多数情况下,您将在应用程序生命周期内只使用一个实现(例如,只使用DispatcherService),那么您基本上需要决定是否需要使用DispatcherService包装请求的iSeries设备。在这种情况下,您可以查看。工厂代理将了解配置,并基于配置将使用DispatcherService包装iSeries设备,或仅返回从容器中获得的iSeries设备实现。

我发现在Castle Windsor IoC容器中执行此操作非常简单。只需按照正确的顺序注册这些类——首先是包装器,然后是包装的类,然后就会发生正确的事情

e、 g

container.Kernel.AddComponent();
container.Kernel.AddComponent();
这不仅是一个批次比Unity更少的麻烦,还保留了IoC的一个关键优势,即如果DispatcherService构造函数的参数更改,则无需更改其他代码


我们希望未来版本的Unity能够让这个场景像温莎一样简单。

太好了,感谢静态工厂的建议。您必须添加对Microsoft.Practices.Unity.StaticFactory的引用。我已经发布了一些示例代码。
public static class ContainerExtensions
{
    public static void RegisterFactory<T>(this IUnityContainer container, FactoryDelegate factoryDelegate)
    {
        container.AddNewExtension<StaticFactoryExtension>()
            .Configure<IStaticFactoryConfiguration>()
            .RegisterFactory<T>(factoryDelegate);
    }
}
container.RegisterType<IService, RealService>("real");
container.RegisterType<IService, DispatcherService>("dispatcher");
[Dependency("real")]
container.Kernel.AddComponent<IService, DispatcherService>();
container.Kernel.AddComponent<IService, RealService>();