我想使用統一解決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