【问题标题】:Autofac: Create named scope on resolvingAutofac:在解析时创建命名范围
【发布时间】:2018-10-18 01:59:01
【问题描述】:

Autofac 是否可以在每次解析另一个特定类型时自动实例化类型并为特定类型创建命名范围?

例如

builder.Register<MyType>.As<IMyType>().InstancePerLifetimeScope();
builder.RegisterAsAutoInstantiateType<IMyType, MySubType>().As<IMySubType>();

class MySubType(IMyType myType)
{
    ...
}

我已经尝试过使用 Owned,使用 OnActivated 并在每次解析 IMyType 时解析 IEnumerable&lt;IMySubType&gt;,但我想要的是为每个 IMyType 创建一个新的生命周期范围,并自动解析并实例化所有为该 IMyType 范围注册的类型。

【问题讨论】:

  • 这是一件相当少见的事情(比如,在我与 Autofac 合作的这些年里,我从未听说过这样的要求)所以我很好奇是否有不同的方法解决您正在查看的问题。也就是说,您已经指定了一个涉及生命周期范围和事物的复杂创建的解决方案……但是要解决的挑战是什么?也许有一种不涉及这种复杂程度的不同方法来处理它。
  • @Travis-Illig 我试着用一句话来表述它:调用者创建类型 A 的对象(分别解析一个 Func() 来创建 As)并且插件应该提供以下类型在创建 As 时自动实例化,它应该是通用的,这样插件不仅可以指定创建 As 时创建的类型,还可以指定其他类型。
  • 最好通过更新您的问题来扩展它。听起来好像有某种插件机制......有“自动实例化的类型”但是什么拥有对它们的引用?被创建并立即失去范围?插件长什么样? (这都应该在问题中,而不是在 cmets 中......)

标签: c# .net autofac


【解决方案1】:

以下代码可根据您的要求运行。唯一的策略是您的类型将被实例化两次。为了克服这个问题,我进行了两次注册。请查看并告诉我们。

        //Lighweight registration
        containerBuilder.RegisterType<TestItem>().As<ITestItem>();


        //Actual regirstation
        containerBuilder.Register((c, qe) =>
        {
            var subType = c.Resolve<IsubType>();
            return new TestItem(subType);

        }).As<ITestItem>().Keyed("TestKey", typeof(ITestItem));


        containerBuilder.RegisterBuildCallback(builtContainer =>
        {
            //Filter for types
            foreach (var registration in builtContainer.ComponentRegistry.Registrations)
            {
                registration.Activating += (sender, eventArgs) =>
                 {
                     var instanseLookup = eventArgs.Context as IInstanceLookup;
                     if (instanseLookup != null && !instanseLookup.ActivationScope.Tag.Equals("Manual"))
                     {
                         var scope = builtContainer.BeginLifetimeScope("Manual");
                         eventArgs.Instance = scope.ResolveKeyed<ITestItem>("TestKey");
                     }


                 };
            }
        });

【讨论】:

  • 不幸的是它没有,因为我不仅想要一件,还想要多件。就像在stackoverflow.com/questions/51710900/… 中一样,但附加要求 A 与 B 和 C 没有关系,但 B 和 C 与 A 有关系,并且应该在创建 A 时自动创建。
  • @TheWizard 您是否希望从为 A 创建的范围中解析 B 和 C?
  • 没错。当 A 被创建时,A 应该在 B 内有自己的范围,C 应该在 A 的解析操作之后(或在?)之后立即创建。应该像你在根范围内有一个对象一样,例如Z 确实如此:public Z(Func&lt;A&gt; create) {... _myListofAs.Add(create()) ... }。然后,Autofac 应该自动处理不再需要的 As(例如,从列表中删除时)并在该生命周期内清理 B 和 C
  • @TheWizard 在上面的代码中,当某些组件请求 ITestItem 实例时,TestItem 是使用“containerBuilder.RegisterType().As();”创建的和Activating 事件发生。在这种情况下,我们再次使用来自新范围的键控注册来创建TestItem 的实例。如果所有BC 都用作参数构造函数,则可以在键控注册中初始化它们。我看到上面的代码满足您的要求。唯一的问题是它为一次调用创建了两次实例。
猜你喜欢
  • 1970-01-01
  • 2014-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多