2011-12-22 56 views
1

我有两个对象应该一起注册,并且共享相同的生命周期范围。我想提供一个注册扩展来封装这个并保持注册的流畅性,但我需要一些帮助。下面就我在的情况:多注册的流利配置

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()?是否有可能直接或间接地“联合”两个对象,以便配置结果可以配置所有基础注册,还是有另一种方法可以执行此操作?

更一般地说:那里是否有与Autofac内部结构一起工作的引子?

谢谢你的时间。

+1

好问题...最好的我能想到的,如果?你想保留基本的语法,就是实现'IRegistrationBuilder 'IIRC,这是这两种类型的最低公分母。不知道这是多么容易,无可否认,Autofac构建流畅UI的方法有一些缺点:) – 2011-12-24 16:27:06

+0

Zoiks。好吧,我没有结婚流利的语法。在我的情况下,我认为只需使用一个采用'Action >'委托,然后在扩展方法内的注册中应用所提供的委托的方法就足够了。你在那看到的任何缺点?我是否违反任何Autofac语义?我可以想象在IRegistrationBuilder <...>的每种方法中重复这一点,但成本效益比现在对我来说没有意义。如果它是Autofac的一部分,也许......这样的实现是否会成为核心的候选者? – 2012-01-09 19:16:00

+0

@NicholasBlumhardt:Oh,BTW:'builder.RegisterType <>()'返回IRegistrationBuilder ',因此两个注册的'LCD'是IRegistrationBuilder '。不知道这是否会让它更难/更容易。 – 2012-01-09 19:35:28

回答

0

天哪,我讨厌回答我的Q,但所有其他说法似乎关闭点或太复杂。尼克的评论最接近吸引人,但只是成功地将我从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()); 

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

0

您应该使用一个模块来封装合理的注册。

恕我直言,你应该在电话号码.SingleInstance()注册。如果他们是两个服务,他们应该配置两次。如果他们在注册时拥有更多的共同点,您可以使用Assembly Scanning进行注册。

+0

通过文档,模块似乎更多地用于整形XML配置(我不使用它)。您需要说明为什么它们比定制的ContainerBuilder扩展更合适。扫描并不是一个坏主意,但是如果一个或两个组件的注册变得更加复杂(代表),则不起作用。也许我过分简化了我的例子,我将编辑和更新。 – 2011-12-23 04:39:12

+0

我认为你误解了文档,看看http://code.google.com/p/autofac/wiki/StructuringWithModules#Common_Use_Cases_for_Modules – rcaval 2011-12-23 13:08:47

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; 
      } 
     } 
    } 
} 
+0

这对我来说有点过分了,尽管有趣的阅​​读。 – 2012-04-19 15:56:27