Я хочу использовать Unity разрешить 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.
У меня есть WPF Ui с использованием контейнера Unity IoC. Наиболее распространенный повторяющийся код связан с обработанными обработчиками - их нужно перенаправить обратно в поток пользовательского интерфейса с помощью Диспетчера. Так что я думаю о обертке, как это:
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? И если да, то работает ли это в Silverlight? Это можно сделать без использования Unity в исходной библиотеке вообще.
я могу работать вокруг с «маркером» интерфейса подкласса, т.е.
public interface IServiceWithDispatcher : IService
{
}
...
UnityContainer container = new UnityContainer();
container.RegisterInstance<Dispatcher>(Application.Current.Dispatcher);
container.RegisterType<IService, RealService>();
container.RegisterType<IServiceWithDispatcher, DispatcherService>();
Но я не думаю, что это хорошая идея, пустой интерфейс некрасиво и это не очень хорошо масштабируется ,
Какой способ разрешить это дерево объектов?
Update:
В соответствии с 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>();
Более полный рабочий код, который лучше подходит для 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