2013-08-23 101 views
1

我有一個Windsor服務和兩個實現它的組件: 一個是「真正」服務,一個是「代理」(作爲裝飾器實現)呼叫「真正」的服務,或者一個web服務。Castle Windsor配置:爲裝飾器設置FromAssembly.InDirectory的訂單

現在理想的情況是,如果找到代理DLL,代理將被用作裝飾器。 如果它不存在,所有的呼叫將直接進入「真實」的服務。

我目前使用「FromAssembly.InDirectory」來註冊組件,而且這個工程就像一個魅力。 但是,我認爲這僅僅是因爲程序集正好以正確的字母順序命名,所以「真正的」服務在「代理」(裝飾器)之前註冊。 (請糾正我,如果我錯了。)

這看起來不太健壯。 有沒有更好的方式來做到這一點,而無需手動配置配置文件中的每個組件?

我要麼喜歡配置文件,我只會按正確的順序列出程序集,並且這些文件中的所有組件都會自動註冊(就像FromAssembly.Named一樣)。

或者 - 甚至會更好 - 某些機制會自動計算出哪個組件是裝飾器(畢竟,它具有對其實現的服務的依賴性,而「真實」服務不會),以及哪一個是「真正的服務」,然後按照正確的順序自動註冊它們。

我當然可以自己實現後者的邏輯,但我不想重新發明輪子。

任何建議將不勝感激。 謝謝!

編輯: 這是我到目前爲止。 如何確定默認組件(裝飾器,如果有,默認組件),以便WCF工具可以通過其名稱找到它? 我的意思是,我可以給裝飾器部件添加一個「命名」調用,但是如果沒有定義裝飾器會怎麼樣?

public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     var currDomain = AppDomain.CurrentDomain; 
     var webAppBinDir = currDomain.RelativeSearchPath; 
     var assemblyDir = (!string.IsNullOrEmpty(webAppBinDir)) ? webAppBinDir : currDomain.BaseDirectory; 

     container.Register(
      Classes.FromAssemblyInDirectory(new AssemblyFilter(assemblyDir, Mask)) 
        .Where(ImplementsServiceContract) 
        .WithServiceSelect((x, y) => GetServices(x)) 
        .ConfigureIf(IsDecorator, c => c.IsDefault(y => IsDecorating(c, y))) 
      ); 
    } 

    private static bool ImplementsServiceContract(Type type) 
    { 
     return GetServices(type).Any(); 
    } 

    private static IEnumerable<Type> GetServices(Type type) 
    { 
     return type.GetInterfaces().Where(IsServiceContract); 
    } 

    private static bool IsServiceContract(Type type) 
    { 
     var ns = type.Namespace; 
     return ns != null && ns.StartsWith(NamespacePrefix) && Attribute.IsDefined(type, typeof(ServiceContractAttribute)); 
    } 

    private static bool IsDecorator(ComponentRegistration c) 
    { 
     Type component = c.Implementation; 
     return GetServices(component).Any(x => IsDecorating(c, x)); 
    } 

    private static bool IsDecorating(ComponentRegistration c, Type service) 
    { 
     Type component = c.Implementation; 
     return service.Assembly != component.Assembly; 
    } 

回答

1

我對這種情況的舊方法是在web.config或專用xml文件中註冊聲明。 從版本3.1開始,您可以爲給定接口指定一個Default組件:使用命名約定策略變得非常容易將裝飾器設置爲默認組件,無論具體註冊如何。

我用來確保註冊順序的另一種方法,不僅僅是裝飾者,而是創建一個InstallerFactory,以便您可以輕鬆地驅動安裝程序的執行順序。

很抱歉,如果我不提供任何代碼示例...但我在休假是對的,現在的裝飾

doco

+0

你能詳細說明這個「默認組件」的東西嗎? 我在哪裏設置? – TravelingFox

+0

您是否在談論「回退組件」(http://docs.castleproject.org/Windsor.Whats-New-In-Windsor-31.ashx)? 這將有助於裝飾者? 我是否可以在一次調用中將其用於所有組件,還是我仍然需要配置每一個組件? – TravelingFox

+0

http://docs.castleproject.org/Windsor.Whats-New-In-Windsor-3.ashx搜索組件現在可以「強制」爲其服務的默認設置,無需成爲第一個註冊¶ – Crixo

1

使用IsDefault如果你沒有一個參考去那個大會(爲什麼不呢?)然後使用.ConfigureIf並以某種方式匹配類型(可能通過名稱)

+0

謝謝!你如何使這個功能強大且易於配置?如果包含程序集存在,我希望裝飾器正確註冊。但FromAssembly.InDirectory依賴於字母順序,不是嗎?我應該編寫自己的InstallerFactory嗎? – TravelingFox

+1

根據我的回答,如果您使用IsDefault,您不再需要InstallerFactory – Crixo

+0

非常感謝您在編輯中的澄清,@ krzysztof-kozmic!我編輯了我的原始問題以包含後續問題。小心看看這個呢? :) – TravelingFox

相關問題