2011-12-22 78 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