具有每事务Func的单身人士<>依赖于Autofac

时间:2017-03-12 06:04:08

标签: .net asp.net-core autofac

我正在使用ASP.NET Core。我是Autofac的新手。

第三方库(NLog)将我的Foo对象用于应用程序的生命周期,因此它实际上变成了单例,我无法改变它。问题是Foo有一个作用域依赖,它实际上也变成了一个单例(一个强制依赖)。

related question中,我被告知将依赖项更改为Func<Dependency>,因此会在每个请求上创建一个新实例。内置容器不支持Func<>,因此我使用的是Autofac。

我的类型:

public class Foo
{
    public Foo(Func<IMyContext> contextFactory) { _contextFactory = contextFactory; }
    private readonly Func<IMyContext> _contextFactory;

    public void doSomething() { /* shown below */ }
}

我的Startup

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IMyContext, MyContext>();
    services.AddSingleton<Foo>();
    var builder = new ContainerBuilder();
    builder.Populate(services);
    return new AutofacServiceProvider(builder.Build());
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory log)
{
    var foo = app.ApplicationServices.GetService<Foo>();
    ConfigureNLog(foo);    // effectively becomes a singleton, and I can't change that
    // ...
}

要在请求期间对此进行测试,请记录实例的哈希码:

public class Foo
{
    // ...

    public void doSomething()
    {
        using (var context = _contextFactory())
        {
            _logger.log(context.GetHashCode());   // should be unique on each request
        }
    }
}

我希望每个请求都有一个唯一的哈希码,因为依赖项是通过Func<>工厂创建的。但它们总是一样的!因此,每个请求都是相同的实例。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

TL; DR;

更改上下文的注册,如下所示:

services.AddTransient<IMyContext, MyContext>();

每次MyContext调用Foo时,这将为您提供Func<IMyContext>的新实例。每次在这里都很重要,因为这意味着如果在同一个HTTP请求期间调用Func 10次,将创建10个不同的实例。

更长的版本

也许我用错误的方式阅读了它,但是我认为你想要达到的目的是:你希望注入Func<IMyContext>的{​​{1}}解析为{{1}的同一个实例每个HTTP请求。

我认为这是不可能的,并且它不是特定于Autofac的问题。

原因是注入Foo的{​​{1}}与根生存期范围相关联 - 因为MyContext本身是从根容器创建的。这意味着Func<IMyContext>Foo都不知道为每个HTTP请求创建的潜在嵌套生命周期范围。

您可以使用的唯一解决方案是,每次容器解析时都会创建Foo的新实例。

这是否符合您的要求?