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);