如何在创建 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 将自动创建。但这不是我想要的。
我可以看到很多方法来做你想做的事。
如果可以修改IDialpad
注册,就可以使用OnActivated
事件。
builder.RegisterType<Foo>()
.As<IFoo>()
.InstancePerOwned<IBar>();
builder.RegisterType<Bar>()
.As<IBar>()
.OnActivated(e => e.Context.Resolve<IFoo>());
如果您无权访问此注册,您可以创建一个模块来执行相同的操作。
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>();
};
}
}
}
基于前面的解决方案,您可以提供一种新型服务,当另一个服务被激活时,将指示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>();
AutoActivateService
和 AutoActivate
的代码如下:
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);
}
}
您还可以使用 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>();
}
}
假设我有以下注册:
builder.RegisterType<ContactsManager>().InstancePerOwned<IDialPad>();
当我创建 Owned<IDialpad>
时,没有 class 在 IDialPad 范围内解析取决于 ContactsManager,因此不会创建 ContactsManager。但我仍然希望它在范围创建时创建。
当我这样做时:
builder.RegisterType<ContactsManager>().InstancePerOwned<IDialPad>().AutoActivate();
它不是在范围创建时激活,而是在 Autofac 容器构建时激活,当然它无法激活。
我知道如果我将对 ContactsManager 的虚假依赖添加到作用域中的任何 class,那么 ContactsManager 将自动创建。但这不是我想要的。
我可以看到很多方法来做你想做的事。
如果可以修改
IDialpad
注册,就可以使用OnActivated
事件。builder.RegisterType<Foo>() .As<IFoo>() .InstancePerOwned<IBar>(); builder.RegisterType<Bar>() .As<IBar>() .OnActivated(e => e.Context.Resolve<IFoo>());
如果您无权访问此注册,您可以创建一个模块来执行相同的操作。
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>(); }; } } }
基于前面的解决方案,您可以提供一种新型服务,当另一个服务被激活时,将指示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>();
AutoActivateService
和AutoActivate
的代码如下: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); } }
您还可以使用
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>(); } }