2017-06-12 64 views
1

我們有一個大的整體的遺留應用程序有大約45個項目,幾個不同的組成根(主機,網絡,應用程序API)執行某些類型的安裝程序的。大多數組件註冊都是在應用程序和許多WindsorInstallers的組合根目錄中完成的。我們希望從組合根和WindsorInstallers中移除解決方案中的每個項目的組件註冊,以便在添加新項目時不再需要修改組合根,每個項目都應該負責其自己的組件註冊。我們正在逐步做,因爲我試過只是有溫莎城堡掃描所有的組件和運行所有的安裝程序的這一變化給我們的代碼庫,但造成的,這將需要一段時間來看待成等種種問題。溫莎城堡只在許多項目

與所有的這麼說,我們正在尋找一種方式,只運行某些安裝程序,所以我們可以回去一段時間修復損壞的,但所有新將自動使用。以下是我所面對的方法,但無法弄清楚或甚至不知道是否有可能。

所有成分根將有這樣的事情,讓所有的安裝程序都總是跑。

container.Install(
      FromAssembly.InDirectory(new AssemblyFilter(HttpRuntime.BinDirectory)) 
     ); 

但是我想這個安裝代碼只運行IAutoInstaller類型的安裝程序。通過這種方式,我可以返回並修復我的舊版安裝程序,只需將接口更改爲IAutoInstaller,然後再也不需要修改組合根。

public interface IAutoInstaller : IWindsorInstaller 
{ 

} 

public class ScheduledPaymentInstaller : IAutoInstaller 
{ 

    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(Classes.FromAssemblyNamed("DryFly.ScheduledPayments") 
      .Pick() 
      .WithServiceDefaultInterfaces().LifestylePerWebRequest()); 

    } 
} 

總之我是後是從該組合物根自動執行某些安裝,這樣,當我添加新的項目,我不需要修改代碼的方式。我只需要爲新項目添加一個新的安裝程序。是否有不同的方法來解決這個問題,或者可以通過Castle Windsor完成嗎?

回答

0

這是可能的,但並不漂亮:

var container = new WindsorContainer(); 
var installers = AppDomain.CurrentDomain 
     .GetAssemblies() // Load all assemblies in the current application domain 
     .SelectMany(s => s.GetTypes()) // project all types contained in all assemblies into a single collection 
     .Where(type => typeof(IAutoInstaller).IsAssignableFrom(type) && type.IsClass) // find all types that implement IAutoInstaller and are classes (this filters out the interface itself) 
     .Select(Activator.CreateInstance) // project all types into instances - this relies on all of them containing a parameterless constructor 
     .Cast<IAutoInstaller>(); // project the Ienumerable<object> into an Ienumerable<IAutoInstaller> 

foreach (var installer in installers) 
{ 
    installer.Install(container, container.Kernel.ConfigurationStore); 
} 

這裏有一個巨大的警告,這是你的安裝必須有一個參數的構造函數這個工作。如果由於某種原因,情況並非如此,那麼您的問題一般難以解決。

不幸的是,IWindsorInstaller接口只強制執行期望容器本身的方法,並且實施了IConfigurationStore。所以即使你不使用配置存儲,你仍然需要提供它。幸運的是,當您使用默認的構造函數,它的電線了一個默認的核心與DefaultConfigurationStore實現實例化一個WindsorContainer。這允許您只通過它。

但是,如果使用自定義配置存儲(例如使用XML配置解釋器時),並且此配置存儲由另一個容器或父級或子級擁有與當前容器相關的容器,並且您需要訪問特定安裝程序中特定商店的值,則必須將該特定商店參考傳遞到安裝程序中。

正如你可以從商店的注意事項清單中看到的,你可能會安全地通過內核默認設置,或者甚至新建一個DefaultConfigurationStore

+0

我假設這個代碼是從組成root身份運行,是否正確?如果是這樣,我如何獲得商店的實例(IConfigurationStore)? – csalzsieder

+0

正確。我也用兩種方式更新了我的答案。我已經詳細闡述了這家商店的實際情況,並通過您的評論進行評論,我假設您並不需要其中一個。在這種情況下,我提供的代碼應該足夠了。其次,我已經有了一個清晰的時刻,給了你一個代碼片段,它可以遍歷所有的安裝程序兩次,一次用於ToList()調用,一次用於Foreach()。如果你的安裝列表很小,那麼它確實沒有什麼區別,但我已經將它恢復到了正常的foreach。 –

+0

我意識到使用當前的應用程序域不會給你所有的程序集,因爲它們在解析引用時會被延遲加載。今天晚些時候我會看看如何加載bin文件夾中的所有內容。 –