【问题标题】:Decorators and property injection in AutofacAutofac 中的装饰器和属性注入
【发布时间】:2020-02-23 17:03:21
【问题描述】:

我正在尝试为这些使用属性注入的服务注册装饰器。
当我添加 containerBuilder.RegisterDecorator<ServiceDecorator, IService>() 时,不再注入属性。
我猜 Autofac 正试图将其注入装饰器而不是原始服务。

我编写了一些测试来展示这个问题。有服务和装饰器:

public interface IService
{
    bool NestedServiceIsNotNull();
}

public interface INestedService { }

public class Service : IService
{
    public INestedService NestedService { get; set; }

    public bool NestedServiceIsNotNull()
    {
        return NestedService != null;
    }
}

public class NestedService : INestedService { }

public class ServiceDecorator : IService
{
    private readonly IService _original;

    public ServiceDecorator(IService original)
    {
        _original = original;
    }

    public bool NestedServiceIsNotNull()
    {
        return _original.NestedServiceIsNotNull();
    }
}

以及测试方法:

[TestMethod]
public void PropertyInjectedServiceShouldNotBeNull()
{
    var builder = new ContainerBuilder();
    builder.RegisterType<NestedService>().As<INestedService>();
    builder.RegisterType<Service>().As<IService>().PropertiesAutowired();
    var container = builder.Build();
    var service = container.Resolve<IService>();

    Assert.IsTrue(service.NestedServiceIsNotNull());
}

[TestMethod]
public void PropertyInjectedServiceShouldNotBeNullEvenIfDecoratorRegistered()
{
    var builder = new ContainerBuilder();
    builder.RegisterType<NestedService>().As<INestedService>();
    builder.RegisterType<Service>().As<IService>().PropertiesAutowired();
    // Here's the difference - decorating the service
    // causes the assertion to fail.
    builder.RegisterDecorator<ServiceDecorator, IService>();
    var container = builder.Build();
    var service = container.Resolve<IService>();

    Assert.IsTrue(service.NestedServiceIsNotNull());
}

第一个测试通过,但第二个断言失败。

这是正确的行为吗?
我正在处理一个遗留项目,所以我不应该通过将依赖项移动到构造函数来更改现有代码。
有没有办法解决这个问题?

【问题讨论】:

  • 我可能会推荐几件事来让更多人参与进来:首先,将代码正确放在问题中是一种很好的做法。很少有人会关注链接并深入研究 GitHub 存储库,即使它很简单。 (如果将代码放在问题中太难,也许需要简化?)其次,我确实看到您的测试被“重构”为具有可选的customConfiguration 参数和单独的容器构建方法。为清楚起见,请考虑展开,以便测试是独立的,人们不必手动跟踪。

标签: c# autofac


【解决方案1】:

看来...您发现了一个错误!哟! I've filed an issue on your behalf here.

不过,一切都不会丢失 - 您仍然可以按照自己的方式使用装饰器,您只需要使用较旧的不太漂亮的 Autofac 装饰器语法来完成它。

var builder = new ContainerBuilder();
builder.RegisterType<NestedService>().As<INestedService>();

// Decorating the service with the old syntax works.
builder.RegisterType<Service>().Named<IService>("service").PropertiesAutowired();
builder.RegisterDecorator<IService>((c, inner) => new ServiceDecorator(inner), fromKey: "service");

var container = builder.Build();
var service = container.Resolve<IService>();

Assert.True(service.NestedServiceIsNotNull());

There is more documentation on how to work with this older syntax here.

【讨论】:

    猜你喜欢
    • 2019-08-08
    • 1970-01-01
    • 2011-12-01
    • 2017-01-26
    • 1970-01-01
    • 2014-12-31
    • 1970-01-01
    • 2012-09-21
    • 1970-01-01
    相关资源
    最近更新 更多