如何在WinRT通用应用程序中使用caliburn micro为以下场景注册装饰器:
我有Caliburn微容器,它是寄存器类型:
_container.RegisterInstance(IService, "", Service);
我创建了以下IService实现和装饰器:
public interface IService
{
void Do();
}
public class Service : IService
{
public void Do() { }
}
public class LoggedService<T> : IService
where T : IService
{
private T decoratee;
private ILogger logger;
public LoggedService(ILogger logger, T decoratee)
{
this.decoratee = decoratee;
this.logger = logger;
}
public void Do()
{
logger.Debug("Do()");
decoratee.Do();
}
}
public class ProfiledService<T> : IService
where T : IService
{
private T decoratee;
private IProfiler profiler;
public ProfiledService(IProfiler profiler, T decoratee)
{
this.decoratee = decoratee;
this.profiler = profiler;
}
public void Do()
{
profiler.Start();
decoratee.Do();
profiler.Stop();
}
}
我如何注册像LoggedService和ProfileService这样的装饰器,并根据有条件的要求来解决这些问题?
答案 0 :(得分:0)
SimpleContainer
在这里辜负了它的名字,它不支持上下文注册等内容。您可以使用命名注册和AddHandler
等功能来创建自定义逻辑。
他们这样做是为Service
添加命名注册,然后为AddHandler
添加IService
,使用实际命名注册的容器实例化装饰器。如果你有两个级别的装饰器,那会有点傻。
如果你真的想要使用装饰器或者有很多装饰器,我建议使用一个更高级的容器,它具有装饰器周围的特定功能。
答案 1 :(得分:0)
你可以这样做,但它可能不是最佳的。我设计了这些解决问题的扩展方法。
我们的想法是创建一个子容器,将装饰器实现注册为自己的服务,然后取消注册原始处理程序,并注册一个使用子容器查找装饰器的新处理程序。
缺点是我们为每个装饰器创建一个新的子容器,但是开销应该可以忽略不计。
public static SimpleContainer RegisterDecorator(this SimpleContainer container, Type service, Type decorator)
{
if (!container.HasHandler(service, null))
{
throw new ArgumentException(nameof(service));
}
var childContainer = container.CreateChildContainer();
childContainer.RegisterSingleton(decorator, null, decorator);
container.UnregisterHandler(service, null);
container.RegisterHandler(service, null, c => childContainer.GetInstance(decorator, null));
return container;
}
public static SimpleContainer Decorate<TService, TDecorator>(this SimpleContainer container)
{
container.RegisterDecorator(typeof(TService), typeof(TDecorator));
return container;
}
用法:
interface IFoo { }
class A : IFoo { }
class B : IFoo
{
public B(IFoo x) { }
}
class C : IFoo
{
public C(IFoo x) { }
}
var container = new SimpleContainer();
container.Singleton<IFoo, A>();
container.Decorate<IFoo, B>();
container.Decorate<IFoo, C>();
var foo = container.GetInstance<IFoo>();
Assert.True(foo is C);