多个注册的流畅配置

本文关键字:配置 注册 | 更新日期: 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());

但是所有(大部分?)灵活性仍然存在