使用工厂时覆盖 AutoFac 范围配置

Overriding AutoFac scoping configuration when using factory

如何配置 AutoFac 以便我每次出厂时都能获得 Context 的新实例。 Content 组件设置为 InstancePerLifetimeScope(),这非常适合我 99% 的使用,但现在我需要对 Context 组件的范围进行一些额外的控制。

class Program
{
    static void Main(string[] args)
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<Box>();
        builder.RegisterType<DbContext>().InstancePerLifetimeScope();

        var container = builder.Build();

        using (var scope = container.BeginLifetimeScope())
        {
            var x = scope.Resolve<Box>();
        }

        Console.ReadKey();
    }
}

class Box
{
    public Box(DbContext.Factory factory)
    {
        factory();
        factory(); // Want this to generate a NEW instance

        Console.WriteLine("Box: {0}", GetHashCode());
    }
}

class DbContext
{
    public delegate DbContext Factory();

    public DbContext()
    {
        Console.WriteLine("Context: {0}", GetHashCode());
    }
}

显然,这是一个相当简化的代码片段。我要解决的问题是,我有大量数据流进入服务,我正在尝试批量保存到数据库。因此,如果 Box 可以按需创建新的 UOW,并及时释放它们以供处置,那么我将得到一个非常干净的解决方案。

谢谢!

您可以使用 Func<Owned<>>,它的工作原理与小型 ILifetimeScope 类似:

public Box(Func<Owned<DbContext>> factory)
{
    using (Owned<DbContext> ownedDbContext = factory())
    {
        // instance1
    }
    using (Owned<DbContext> ownedDbContext = factory())
    {
        // instance2 
    }
}

您可以在 Autofac 文档中找到更多详细信息:Owned Instances

另一个解决方案是注入 ILifetimeScope 然后创建一个子生命周期:

public Box(ILifetimeScope scope)
{
    using (ILifetimeScope subScope = scope.BeginLifetimeScope())
    {
        DbContext dbContext = subScope.Resolve<DbContext>();
    }
}

public Box(ILifetimeScope scope)
{
    ILifetimeScope subScope = scope.BeginLifetimeScope();
    scope.Disposer.AddInstanceForDisposal(subScope);
    DbContext dbContext = subScope.Resolve<DbContext>(); 
    // no need to dispose subScope, 
    // subScope (and dbContext) will be disposed at the same time as scope
}