2013-06-28 122 views
3

我想了解如何動態加載DLL到C#程序中。這個想法是,DLL將包含一個接口和幾個不同的接口實現,所以如果我想添加新的實現,我不必重新編譯我的整個項目。動態加載DLL接口

所以我創建了這個測試。這裏是我的DLL文件:

namespace TestDLL 
{ 
    public interface Action 
    { 
    void DoAction(); 
    } 

    public class PrintString : Action 
    { 
    public void DoAction() 
    { 
     Console.WriteLine("Hello World!"); 
    } 
    } 

    public class PrintInt : Action 
    { 
    public void DoAction() 
    { 
     Console.WriteLine("Hello 1!"); 
    } 
    } 
} 

而在我的主程序我試圖做這樣的事情:

static void Main(string[] args) 
{ 
    List<Action> actions = new List<Action>(); 
    Assembly myDll = Assembly.LoadFrom("TestDLL.dll"); 
    Type[] types = myDll.GetExportedTypes(); 

    for (int i = 0; i < types.Length; i++) 
    { 
    Type type = types[i]; 
    if (type.GetInterface("TestDLL.Action") != null && type != null) 
    { 
     Action new_action = myDll.CreateInstance(type.FullName) as Action; 
     if (new_action != null) 
      actions.Add(new_action); 
     else 
      Console.WriteLine("New Action is NULL"); 
    } 
    } 

    foreach (Action action in actions) 
    action.DoAction(); 
} 

,我有是問題,即使

type.FullName 

包含正確的值(「TestDLL.PrintString」等),

該行

myDll.CreateInstance(type.FullName) as Action 

總是返回空值。

我不完全確定問題是什麼,或者我可以如何解決它。

就像在這個例子中,我希望能夠將新的Action實現添加到DLL中,並讓主程序在每個這些實現上調用DoAction(),而無需重新編譯原始程序。希望這是有道理的!

+0

您正在使用的'Action',在'as Action'中,定義在哪裏?你是用第一段代碼來引用程序集,還是在你從TestDLL.dll加載的程序集中,有一次在你的主項目中有'Action'聲明瞭兩次? –

回答

2

很可能您的Action在主要和「其他」組件中都被定義,並且您正在投射錯誤的一個。

通常,共享接口在單獨的程序集(「SDK」)中定義,並且與主應用程序和插件程序集都鏈接。通過源共享接口不起作用,因爲類的標識包括程序集名稱和類型名稱。

詳情參見:Cannot get types by custom attributes across assemblies

1

通過您的主要實現您做的更好這個

  List<object> actions = new List<object>(); 
      Assembly myDll = Assembly.LoadFrom("TestDLL.dll"); 
      Type[] types = myDll.GetTypes(); 

      for (int i = 0; i < types.Length; i++) 
      { 
       Type type = myDll.GetType(types[i].FullName); 
       if (type.GetInterface("TestDLL.Action") != null) 
       { 
        object obj = Activator.CreateInstance(type); 
        if (obj != null) 
         actions.Add(obj); 
       } 
      } 

      foreach (var action in actions) 
      { 
       MethodInfo mi = action.GetType().GetMethod("DoAction"); 
       mi.Invoke(action, null); 
      } 

,你應該在try/catch塊包裹這件事。 而當您編寫Action(因爲您沒有爲您的程序集設置參考),如在List<Action>中,此操作是指Action委託。