WinRT Caliburn Micro SimpleContainer:在容器中注册装饰器
WinRT Caliburn Micro SimpleContainer: registering a decorator in a container
如何在 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,并根据有条件地需要解决这些问题?
SimpleContainer
名副其实,它不支持上下文注册等功能。您可以使用命名注册和 AddHandler
等功能来创建自定义逻辑。
他们这样做的方式是为 Service
添加一个命名注册,然后为 IService
添加一个命名注册,然后为 IService
添加一个使用容器实例化装饰器的实际命名注册。如果你有两层装饰器,那就有点傻了。
如果您认真使用装饰器或者有很多装饰器,我建议您使用围绕装饰器具有特定功能的更高级的容器。
您可以这样做,但它可能不是最佳选择。我设计了这些解决问题的扩展方法。
我们的想法是创建一个子容器,将装饰器实现注册为它自己的服务,然后取消注册原始处理程序,并注册一个使用子容器查找装饰器的新处理程序。
缺点是我们为每个注册的装饰器创建一个新的子容器,但是开销应该可以忽略不计。
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);
如何在 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,并根据有条件地需要解决这些问题?
SimpleContainer
名副其实,它不支持上下文注册等功能。您可以使用命名注册和 AddHandler
等功能来创建自定义逻辑。
他们这样做的方式是为 Service
添加一个命名注册,然后为 IService
添加一个命名注册,然后为 IService
添加一个使用容器实例化装饰器的实际命名注册。如果你有两层装饰器,那就有点傻了。
如果您认真使用装饰器或者有很多装饰器,我建议您使用围绕装饰器具有特定功能的更高级的容器。
您可以这样做,但它可能不是最佳选择。我设计了这些解决问题的扩展方法。
我们的想法是创建一个子容器,将装饰器实现注册为它自己的服务,然后取消注册原始处理程序,并注册一个使用子容器查找装饰器的新处理程序。
缺点是我们为每个注册的装饰器创建一个新的子容器,但是开销应该可以忽略不计。
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);