如何在创建 Owner lifetimescope 时自动激活 Autofac 组件?

How to auto activate Autofac component on creating of Owner lifetimescope?

假设我有以下注册:

builder.RegisterType<ContactsManager>().InstancePerOwned<IDialPad>();

当我创建 Owned<IDialpad> 时,没有 class 在 IDialPad 范围内解析取决于 ContactsManager,因此不会创建 ContactsManager。但我仍然希望它在范围创建时创建。

当我这样做时:

builder.RegisterType<ContactsManager>().InstancePerOwned<IDialPad>().AutoActivate();

它不是在范围创建时激活,而是在 Autofac 容器构建时激活,当然它无法激活。

我知道如果我将对 ContactsManager 的虚假依赖添加到作用域中的任何 class,那么 ContactsManager 将自动创建。但这不是我想要的。

我可以看到很多方法来做你想做的事。

  1. 如果可以修改IDialpad注册,就可以使用OnActivated事件。

    builder.RegisterType<Foo>()
           .As<IFoo>()
           .InstancePerOwned<IBar>();
    builder.RegisterType<Bar>()
           .As<IBar>()
           .OnActivated(e => e.Context.Resolve<IFoo>());
    
  2. 如果您无权访问此注册,您可以创建一个模块来执行相同的操作。

    class TestModule : Module
    {
        protected override void AttachToComponentRegistration(
            IComponentRegistry componentRegistry,
            IComponentRegistration registration)
        {
            if (registration.Services
                  .Any(s => s is IServiceWithType 
                            && ((IServiceWithType)s).ServiceType == typeof(IBar)))
            {
                registration.Activated += (sender, e) =>
                {
                    e.Context.Resolve<IFoo>();
                };
            }
        }
    }
    
  3. 基于前面的解决方案,您可以提供一种新型服务,当另一个服务被激活时,将指示Autofac激活指定的服务。

    最终注册将如下所示:

        ContainerBuilder builder = new ContainerBuilder();
        builder.RegisterModule(new AutoActivateModule());
        builder.RegisterType<Foo>()
                .As<IFoo>()
                .As(AutoActivateService.From<IBar>())
                .InstancePerOwned<IBar>();
        builder.RegisterType<Bar>()
                .As<IBar>();
    

    AutoActivateServiceAutoActivate 的代码如下:

    public class AutoActivateModule : Module
    {
        protected override void AttachToComponentRegistration(
            IComponentRegistry componentRegistry,
            IComponentRegistration registration)
        {
            foreach (IServiceWithType typedService in registration.Services.OfType<IServiceWithType>())
            {
                registration.Activated += (sender, e) =>
                {
                    Service autoActivateService = AutoActivateService.From(typedService.ServiceType);
                    foreach (IComponentRegistration r in componentRegistry.RegistrationsFor(autoActivateService))
                    {
                        e.Context.ResolveComponent(r, new Parameter[0]);
                    }
                };
            }
        }
    }
    
    public class AutoActivateService : Service, IEquatable<AutoActivateService>
    {
    
        public static AutoActivateService From<T>()
        {
            return new AutoActivateService(typeof(T));
        }
        public static AutoActivateService From(Type targetType)
        {
            return new AutoActivateService(targetType);
        }
    
    
        private AutoActivateService(Type targetType)
        {
            this._targetType = targetType;
        }
    
    
        private readonly Type _targetType;
    
    
        public override String Description
        {
            get { return this.ToString(); }
        }
        public Type TargetType
        {
            get
            {
                return this._targetType;
            }
        }
    
    
        public Boolean Equals(AutoActivateService other)
        {
            return other != null
                   && this._targetType == other._targetType;
        }
        public override Boolean Equals(Object obj)
        {
            return this.Equals(obj as AutoActivateService);
        }
        public override Int32 GetHashCode()
        {
            return this._targetType.GetHashCode();
        }
        public override String ToString()
        {
            return String.Format("Autoactivate service for {0}", this._targetType);
        }
    }
    
  4. 您还可以使用 BeginLifetimeScope 事件。

    激活 Owned<T> 服务后,将创建一个新的 ILifetimeScope,其标签将是关联的服务。

    container.ChildLifetimeScopeBeginning += ChildLifetimeScopeBeginning;
    
    // ...
    
    private static void ChildLifetimeScopeBeginning(
        Object sender, LifetimeScopeBeginningEventArgs e)
    {
        e.LifetimeScope.ChildLifetimeScopeBeginning += ChildLifetimeScopeBeginning;
    
        IServiceWithType typedService = e.LifetimeScope.Tag as IServiceWithType;
        if (typedService != null && typedService.ServiceType == typeof(IBar))
        {
            e.LifetimeScope.Resolve<IFoo>();
        }
    }