WinRT Caliburn Micro SimpleContainer:在容器中注册装饰器

时间:2015-04-14 12:12:34

标签: c# wpf windows-runtime ioc-container caliburn.micro

如何在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这样的装饰器,并根据有条件的要求来解决这些问题?

2 个答案:

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