首页 > 解决方案 > 在标记范围和未标记范围内解析组件

问题描述

我正在尝试为 AutoFac 中的某些标记的生命周期范围提供不同的服务,但似乎无法掌握它。

我已经尝试在每个匹配的生命周期范围内使用来自 Instance 的自定义生命周期,默认情况下?但这没有用。

我写了一个测试来说明我正在尝试做的事情:

[TestMethod]
public void NamedLifetimeTests()
{
    var builder = new ContainerBuilder();
    builder.Register(c => new ChildA()).As<Parent>().InstancePerLifetimeScope();
    builder.Register(c => new ChildB()).As<Parent>().InstancePerMatchingLifetimeScope("system").PreserveExistingDefaults();

    var container = builder.Build();
    using (var scope = container.BeginLifetimeScope())
    {
        var parent = scope.Resolve<Parent>();
        Assert.IsTrue(parent.GetType() == typeof(ChildA));
    }

    using (var scope = container.BeginLifetimeScope("system"))
    {
        var parent = scope.Resolve<Parent>();
        Assert.IsTrue(parent.GetType() == typeof(ChildB));
    }
}

这可能吗?

标签: c#dependency-injectionautofac

解决方案


解决方案可能是在创建范围时为生命周期范围提供这些自定义服务。在创建新的生命周期范围时,container.BeginLifetimeScope您可以提供附加Action<ContainerBuilder>参数来定义此特定生命周期范围的一些自定义注册。

因此,对于您的代码,ChildB您可以将其移至按范围注册,而不是全局注册。它可能看起来像这样:

[TestMethod]
public void NamedLifetimeTests()
{
    var builder = new ContainerBuilder();
    builder.Register(c => new ChildA()).As<Parent>().InstancePerLifetimeScope();    

    var container = builder.Build();
    using (var scope = container.BeginLifetimeScope())
    {
        var parent = scope.Resolve<Parent>();
        Assert.IsTrue(parent.GetType() == typeof(ChildA));
    }

    using (var scope = container.BeginLifetimeScope("system"), cb => { cb.RegisterType<ChildB>().As<Parent>(); }))
    {
        var parent = scope.Resolve<Parent>();
        Assert.IsTrue(parent.GetType() == typeof(ChildB));
    }
}

编辑:避免注入生命周期范围是可以理解的。另一种解决方案可能是根据生命周期标签选择适当的实现,类似于基于参数选择实现,在文档中描述:

// omitted ...
var builder = new ContainerBuilder();
builder.Register<Parent>(c =>
    {
        var currentScope = c.Resolve<ILifetimeScope>();
        if (currentScope.Tag?.ToString() == "system")
        {
            return new ChildB();
        }

        return new ChildA();
    }).InstancePerLifetimeScope();   

var container = builder.Build();
// omitted ...

推荐阅读