如何注册装饰器以解决装饰器

时间:2018-10-24 13:43:13

标签: c# autofac autofac-configuration

我正在使用Autofac。 我正在尝试使用装饰器模式使用相同的接口注册2个类。

public interface IDoable
{
    string Do();
}

public class Decoree : IDoable
{
    public string Do()
    {
        return "decoree";
    }
}

public class Decorator : IDoable
{
    public IDoable InnerDecoree { get; set; }

    public Decorator(IDoable doable)
    {
        this.InnerDecoree = doable;
    }

    public string Do()
    {
        return InnerDecoree.Do() + "decorator";
    }
}

我想使用容器来解决2种不同情况下的两种类型:

  • IDoable,我希望该实例是Decorator的实例
  • 用于特定的Decoree,在这里我确实需要解析特定的Decoree实例。

我只能通过以下代码来实现它:

[Fact]
public void Both()
{
    var builder = new ContainerBuilder();
    builder.RegisterType<Decoree>()
           .Named<IDoable>("decoree")
           .SingleInstance();

    builder.RegisterType<Decoree>() // but this is not right I'd like to register it on line above somehow...
        .AsSelf()
        .SingleInstance(); 

    builder.RegisterType<Decorator>()
           .Named<IDoable>("decorator")
           .SingleInstance();

    builder.RegisterDecorator<IDoable>(
            (c, inner) => c.ResolveNamed<IDoable>("decorator", TypedParameter.From(inner)), "decoree")
            .As<IDoable>();

    var container = builder.Build();

    Assert.IsType<Decoree>(container.Resolve<Decoree>());
    Assert.False(container.IsRegistered<Decorator>());
    Assert.IsType<Decorator>(container.Resolve<IDoable>());


    var decoree = container.Resolve<Decoree>();
    var decorator = container.Resolve<IDoable>();
    var doable = ((Decorator)decorator).InnerDecoree;

    Assert.Same(decoree, doable); // FALSE :(

}

问题是,我真的很希望最后一个断言为true :),所以它是同一实例。

基本上我的问题是:是否可以使用 named type 两种方式注册类型?

1 个答案:

答案 0 :(得分:2)

由于您没有在注册中指定范围,因此每次Decoree解析时都会得到一个不同的实例。我会尝试类似的

builder.RegisterType<Decoree>()
       .Named<IDoable>("decoree").SingleInstance();

此外,您可能需要合并两个Decoree类型的注册:

builder.RegisterType<Decoree>()
       .Named<IDoable>("decoree")
       .AsSelf()
       .SingleInstance();