在 Autofac 中使用 RegistrationSource 自动注册
Auto-registration with a RegistrationSource in Autofac
这是我目前所做的(代码已简化):
public class MyRegistrationSource : IRegistrationSource
{
public MyRegistrationSource(ContainerBuilder builder /*,...*/)
{
// ...
this.builder = builder;
}
public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
// Some checks here
var interfaceType = serviceWithType.ServiceType;
var implementorType = FindTheRightImplementor(interfaceType);
if (myRegisterConditionSatisfied)
{
return Register(implementorType, interfaceType);
}
return Empty;
}
private IEnumerable<IComponentRegistration> Register(Type concrete, Type @interface)
{
var regBuilder = builder.RegisterType(concrete).As(@interface).IfNotRegistered(@interface);
return new[] { regBuilder.CreateRegistration() };
}
}
然后,在启动时我正在做类似
的事情
builder.RegisterSource(
new NonRegisteredServicesRegistrationSource(builder/*, ...*/));
以上是为了在之前没有注册的情况下才注册那些匹配的服务。我尝试在不使用 ContainerBuilder
的情况下进行注册,但无法正常工作。
这是可行的,但是在将 ContainerBuilder
实例传递给 RegistrationSource
时是否存在任何问题?
谢谢!
我可能反对传递 ContainerBuilder
。
您在源代码中注册的每种类型都会向 Container Builder 中的回调列表添加一个回调,该列表永远不会被清除,可能会造成内存泄漏。
我建议改为调用静态方法 RegistrationBuilder.ForType
,这将为您提供一个流畅的构建器,并且应该让您随后像现在一样调用 CreateRegistration
。
您可以在我们的 Moq integration:
中看到一些很好的例子来说明如何做到这一点
var reg = RegistrationBuilder.ForType(concrete)
.As(@interface)
.CreateRegistration();
此外,我认为 IfNotRegistered
在 ContainerBuilder
的上下文之外使用时不会有任何效果。你应该使用注册源提供的registrationAccessor
参数来查找一个TypedService
看是否已经被注册:
var isRegistered = registrationAccessor(new TypedService(@interface)).Any();
这是我目前所做的(代码已简化):
public class MyRegistrationSource : IRegistrationSource
{
public MyRegistrationSource(ContainerBuilder builder /*,...*/)
{
// ...
this.builder = builder;
}
public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
// Some checks here
var interfaceType = serviceWithType.ServiceType;
var implementorType = FindTheRightImplementor(interfaceType);
if (myRegisterConditionSatisfied)
{
return Register(implementorType, interfaceType);
}
return Empty;
}
private IEnumerable<IComponentRegistration> Register(Type concrete, Type @interface)
{
var regBuilder = builder.RegisterType(concrete).As(@interface).IfNotRegistered(@interface);
return new[] { regBuilder.CreateRegistration() };
}
}
然后,在启动时我正在做类似
的事情builder.RegisterSource(
new NonRegisteredServicesRegistrationSource(builder/*, ...*/));
以上是为了在之前没有注册的情况下才注册那些匹配的服务。我尝试在不使用 ContainerBuilder
的情况下进行注册,但无法正常工作。
这是可行的,但是在将 ContainerBuilder
实例传递给 RegistrationSource
时是否存在任何问题?
谢谢!
我可能反对传递 ContainerBuilder
。
您在源代码中注册的每种类型都会向 Container Builder 中的回调列表添加一个回调,该列表永远不会被清除,可能会造成内存泄漏。
我建议改为调用静态方法 RegistrationBuilder.ForType
,这将为您提供一个流畅的构建器,并且应该让您随后像现在一样调用 CreateRegistration
。
您可以在我们的 Moq integration:
中看到一些很好的例子来说明如何做到这一点var reg = RegistrationBuilder.ForType(concrete)
.As(@interface)
.CreateRegistration();
此外,我认为 IfNotRegistered
在 ContainerBuilder
的上下文之外使用时不会有任何效果。你应该使用注册源提供的registrationAccessor
参数来查找一个TypedService
看是否已经被注册:
var isRegistered = registrationAccessor(new TypedService(@interface)).Any();