多个注册的流畅配置
本文关键字:配置 注册 | 更新日期: 2023-09-27 18:18:33
我有两个对象应该一起注册,并且也共享相同的生命周期范围。我想提供一个注册扩展封装这一点,并保留注册流畅性,但我需要一些帮助。我的情况是这样的:
public static IRegistrationBuilder<?, ?, ?>
RegisterChannel<T>(this ContainerBuilder builder, Func<IComponentContext, ChannelFactory<T>> @delegate)
{
// channelfactory and sharedchannel should have same lifetime configuration
var channelfactoryreg = builder.Register(c => @delegate(c));
var sharereg = builder.RegisterType<Wcf.SharedChannel<T>>();
// is it possible to combine them and return?
return ???;
}
我该如何填空才能写出(例如)builder.RegisterTwo().SingleInstance()
?是否有可能直接或间接地"联合"两个IRegistrationBuilderTLAR
对象,以便配置结果配置所有底层注册,或者有其他方法可以做到这一点?
更一般地说:是否有一个入门书在那里与Autofac内部工作?
感谢您的宝贵时间。
你应该使用一个模块来封装那些有意义的注册。
恕我直言,您应该在两个注册中调用.SingleInstance()
。如果它们是两个服务,则应该配置两次。如果它们在注册中有更多的共性,您可以使用汇编扫描来注册它们。
我发现我越来越多地使用IRegistrationSource接口来将任何相关的注册分组在一起。在您的示例中,它们将使您能够对任意一组类型使用相同的注册码:
public class MyRegistrationSource : IRegistrationSource
{
/// <summary>
/// Gets a value indicating whether the registrations provided by this source are 1:1 adapters on top
/// of other components (I.e. like Meta, Func or Owned.)
/// </summary>
public bool IsAdapterForIndividualComponents
{
get
{
return false;
}
}
/// <summary>
/// Retrieve registrations for an unregistered service, to be used
/// by the container.
/// </summary>
/// <param name="service">The service that was requested.</param>
/// <param name="registrationAccessor">A function that will return existing registrations for a service.</param>
/// <returns>
/// Registrations providing the service.
/// </returns>
public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var swt = service as IServiceWithType;
if (swt != null)
{
// Register requested service types that pass some test or other
if (swt.ServiceType.HasAttribute<SomeAttribute>(true) ||
typeof(SomeType).IsAssignableFrom(swt.ServiceType))
{
var registration = RegistrationBuilder.ForType(swt.ServiceType)
.InstancePerDependency()
.CreateRegistration();
yield return registration;
}
}
}
}
天哪,我讨厌回答自己的问题,但所有建议的替代方案似乎都偏离了主题,或者太复杂了。Nick的评论是最接近吸引人的,但只是成功地把我从autoface内部吓跑了;)我调查了一下,但对我的情况来说,这有点过分了。
我最终把差异分开了(正如我上面的评论所暗示的那样),放弃了流畅的接口,但仍然允许通过接受配置到方法本身来灵活地延续注册:
public static void RegisterSharedChannel<T>(this ContainerBuilder builder, Func<IComponentContext, ChannelFactory<T>> @delegate,
Action<Autofac.Builder.IRegistrationBuilder<object, Autofac.Builder.IConcreteActivatorData, Autofac.Builder.SingleRegistrationStyle>> config)
{
builder.Register(c => c.Resolve<Wcf.ISharedChannel<T>>().GetChannel()).ExternallyOwned();
//would be really nice to be able to retain the fluency of the interface, but: http://stackoverflow.com/questions/8608415/fluent-configuration-of-multiple-registrations
//this should suffice for now...
var facreg = builder.Register(c => @delegate(c));
var sharereg = builder.RegisterType<Wcf.SharedChannel<T>>().AsImplementedInterfaces();
config(facreg);
config(sharereg);
}
调用语法不那么漂亮(例如:
)builder.RegisterSharedChannel(c => BuildChannelFactory(...), r => r.SingleInstance());
但是所有(大部分?)灵活性仍然存在