2012-03-07 54 views
2

我們使用unity作爲IoC。我們遇到了獨特的問題。 我們已經創建了名爲IPlugin的接口。這個接口在不同的第三方供應商之間共享,基於這個接口開發他們自己的插件。這些插件然後適合我們的系統。 供應商將提供他們的插件作爲DLL。我們想要的是, 使用統一性,我們想要解析所有使用IPlugin接口實現的程序集類型。我知道這是通過MEF導出屬性實現的,我想知道這是否可以通過Unity使用一些短的擴展來實現。Unity IoC動態解析程序集

我們的代碼

Public interface IPlugin 
{ 
    Void ProcessData(); 
} 

Public class DataProcessor 
{ 
    Var pluginList = unityContainer.ResolveAssemblies<IPlugIn>() 
/* 
There is no such method in unity but what we want is scan all assemblies in bin folder and load all types which are inheriting from IPlugIn 
*/ 
} 

供應商的組件

Public class AbcCompanyPlugIn : IPlugin 
{ 
Void ProcessData() 
{ 
// some code 
} 

} 
Public class XyzCompanyPlugIn : IPlugin 
{ 
Void ProcessData() 
{ 
// some code 
} 

} 
+0

這是MEF的主要用例之一,您可以考慮將其用於應用程序的插件部分(同時讓Unity保留其餘的IoC需求)。 – dlev 2012-03-07 03:59:22

+0

這不是設計目標Unity或其他IoC框架。所以如果你想要它,就像@dlev所建議的那樣堅持MEF。 – 2012-03-07 06:08:46

+1

@LexLi我不同意這不是DI容器工作的一部分。它們旨在組裝鬆散耦合的應用程序。這與加載插件並將其添加到應用程序有何不同? – 2012-03-07 07:09:10

回答

5

你可以寫一點思考代碼掃描外接組件的文件夾,並用容器註冊所有IPlugin實現。

像這樣的東西應該工作:

var assemblies = // read all assemblies from disk 
var pluginTypes = from a in assemblies 
        from t in a.GetExportedTypes() 
        where typeof(IPlugin).IsAssignableFrom(t) 
        select t; 

foreach (var t in pluginTypes) 
    container.RegisterType(typeof(IPlugin), t); 

(代碼可能無法編譯)

+0

可以在[codec]上的[TecX項目](http://tecx.codeplex.com)中找到它的實現。它是Unity的增強型配置引擎的一部分。請參閱_TecX.Unity.Configuration_ – 2012-03-07 07:07:33

+2

謝謝,這幫助我走了。但是,請注意'IsAssignableFrom(t)'將對類和接口都返回true,因此您可能需要在迭代類型時添加對「IsClass」的檢查。另外,通過在'container.RegisterType()'方法調用中不指定註冊名稱,您將覆蓋每個以前的註冊(導致只有一個註冊類型),因此需要爲註冊方法添加另一個參數,併爲每個註冊方法指定一個唯一的名稱輸入你註冊的名字,比如't.FullName',這樣就可以註冊多個類型來實現'IPlugin'。 – BenSwayne 2013-02-20 21:27:15

3
var assemblies = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "Worker*.dll").Select(f => Assembly.LoadFile(f)).ToArray<Assembly>(); 

    (from asm in assemblies 
     from t in asm.GetExportedTypes() 
     where typeof(ICommonWorker).IsAssignableFrom(t) && t.IsClass 
     select t).ForEach(x => 
    { 
     unityContainer.RegisterType(typeof(ICommonWorker), x, x.FullName, new ContainerControlledLifetimeManager()); 
    }); 

如果現在還有人關心,這是我做的加載DLL的動態,其實現特定的接口(ICommonWorker)。

+0

請小心使用getfiles,因爲即使單個文件存在讀取訪問問題,也會引發異常。否則,這就是我如何使用AutoFac來完成它。 Autofac有模塊可以繼承,也可以用它作爲標記。 http://devkimchi.com/631/dynamic-module-loading-with-autofac/ – 2016-09-16 07:33:29