我想使用统一解决IService
两种不同的实现方式,尽量使用一个包装类的,相当于:解决包装类在C#中使用Unity IoC容器
IService service = new DispatcherService(new RealService(), Application.Current.Dispatcher);
如果双方DispatcherService
和RealService
实施接口IService
。
我有一个包含一些异步操作服务的库。这种服务的简化形式如下所示:
public interface IService
{
IAsyncResult StartSomeOperation();
event EventHandler<EventArgs> SomeOperationCompleted;
}
我有所有这些服务的实现。我希望这个库保持对WPF和IoC容器的依赖,但是在IoC容器和可能的WPF正在使用的情况下可以最好地使用。
我有一个使用Unity IoC容器的WPF UI。最常见的重复代码是围绕完成的处理程序 - 它们需要使用分派器整理回UI线程。所以我想的包装,像这样:
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);
}
}
}
我可以将新这个了类似的代码
IService service = new DispatcherService(new RealService(), Application.Current.Dispatcher);
但整体并不喜欢我创作的两种不同的实现的事实IService接口。 此代码可怕的失败:
UnityContainer container = new UnityContainer();
container.RegisterInstance<Dispatcher>(Application.Current.Dispatcher);
container.RegisterType<IService, RealService>();
container.RegisterType<IService, DispatcherService>();
IService created = container.Resolve<IService>();
如果我在另外的顺序登记服务,首次注册将被覆盖,我只是得到一个RealService
。
Unity有没有办法解决这个问题?或者在Unity的AOP中完成了这一切?如果是这样,那么在Silverlight中工作吗?完全可以在原始库中不使用Unity的情况下完成。
我可以解决一个“标记”接口的子类,即
public interface IServiceWithDispatcher : IService
{
}
...
UnityContainer container = new UnityContainer();
container.RegisterInstance<Dispatcher>(Application.Current.Dispatcher);
container.RegisterType<IService, RealService>();
container.RegisterType<IServiceWithDispatcher, DispatcherService>();
但我不认为这是一个好主意,空接口是丑陋的,这将无法很好地扩展。
解决这个对象树的方法是什么?
更新:
与Dzmitry虎霸的给出了答案线,下面是一些示例代码:
增加提及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>();
更完整的工作代码,更好地处理p otential依赖真正的服务,如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>()
另外,考虑到工厂登记是非常啰嗦了,我会做他们的不止一个,我做了一个扩展方法:
public static class ContainerExtensions
{
public static void RegisterFactory<T>(this IUnityContainer container, FactoryDelegate factoryDelegate)
{
container.AddNewExtension<StaticFactoryExtension>()
.Configure<IStaticFactoryConfiguration>()
.RegisterFactory<T>(factoryDelegate);
}
}
非常感谢静态工厂的建议。 您必须添加对Microsoft.Practices.Unity.StaticFactory的引用。 我发布了一些示例代码。 – Anthony 2010-01-01 19:29:37