我有两个应该一起注册的对象,并且还共享相同的生命期范围。我想提供一个注册扩展来封装这个并保持注册流畅性,但我需要一些帮助。这是我所处的情况:
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内部构件的底漆?
感谢您的时间。
答案 0 :(得分:0)
您应该使用模块来封装有意义的注册。
恕我直言,您应该在两次注册时都致电.SingleInstance()
。如果它们是两个服务,则应配置两次。如果他们在注册时共享更多共性,您可以使用Assembly Scanning注册它们。
答案 1 :(得分:0)
我发现我越来越多地使用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;
}
}
}
}
答案 2 :(得分:0)
天哪,我讨厌回答我自己的问题,但所有建议的替代方案似乎都是非常复杂的。尼克的评论最接近参与,但只是成功地吓跑了我的Autofac内部完全;)。我调查过,但这对我的情况来说太过分了。
我最终分裂了差异(正如我在上面的评论中暗示的那样),放弃了流畅的界面,但仍允许通过接受方法本身的配置来灵活地继续注册:
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());
但所有(大部分?)的灵活性仍然存在。