2013-08-21 93 views
46

我想弄清楚如何在C#應用程序的運行時導入和使用.dll。使用Assembly.LoadFile()我已經設法讓我的程序加載DLL(這部分是肯定工作的,因爲我可以用ToString())獲得類的名稱,但是我無法使用'Output'方法從我的控制檯應用程序中。我正在編譯.dll,然後將它移到我的控制檯項目中。 CreateInstance之間是否存在額外的步驟,然後才能使用這些方法?在C#運行時加載DLL#

這是我的DLL類:

namespace DLL 
{ 
    using System; 

    public class Class1 
    { 
     public void Output(string s) 
     { 
      Console.WriteLine(s); 
     } 
    } 
} 

,這裏是我想要加載DLL

namespace ConsoleApplication1 
{ 
    using System; 
    using System.Reflection; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll"); 

      foreach(Type type in DLL.GetExportedTypes()) 
      { 
       var c = Activator.CreateInstance(type); 
       c.Output(@"Hello"); 
      } 

      Console.ReadLine(); 
     } 
    } 
} 
應用
+0

http:// stackoverflow。com/questions/2202381/reflection-how-to-invoke-method-with-parameters – Stu

回答

74

成員必須在編譯時解析直接從C#叫。否則,您必須使用反射或動態對象。

反思

namespace ConsoleApplication1 
{ 
    using System; 
    using System.Reflection; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll"); 

      foreach(Type type in DLL.GetExportedTypes()) 
      { 
       var c = Activator.CreateInstance(type); 
       type.InvokeMember("Output", BindingFlags.InvokeMethod, null, c, new object[] {@"Hello"}); 
      } 

      Console.ReadLine(); 
     } 
    } 
} 

動態(.NET 4.0)

namespace ConsoleApplication1 
{ 
    using System; 
    using System.Reflection; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll"); 

      foreach(Type type in DLL.GetExportedTypes()) 
      { 
       dynamic c = Activator.CreateInstance(type); 
       c.Output(@"Hello"); 
      } 

      Console.ReadLine(); 
     } 
    } 
} 
+5

請注意,這會嘗試在程序集中的每個類型上調用Output,這可能會在找到「right」類之前拋出。 –

+1

@ReedCopsey,同意,但就他的簡單例子而言,他的類型是唯一可見的類型。 「程序集外可見的唯一類型是嵌套在其他公共類型中的公共類型和公共類型。」對於一個不平凡的例子,顯然這將是一個問題... –

+1

整潔的兩個例子! :) –

25

現在,你創建的在裝配定義的每一個類型的實例。你只需要以創造的Class1單個實例調用的方法:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll"); 

     var theType = DLL.GetType("DLL.Class1"); 
     var c = Activator.CreateInstance(theType); 
     var method = theType.GetMethod("Output"); 
     method.Invoke(c, new object[]{@"Hello"}); 

     Console.ReadLine(); 
    } 
} 
7

您需要創建暴露出Output方法類型的實例:

static void Main(string[] args) 
    { 
     var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll"); 

     var class1Type = DLL.GetType("DLL.Class1"); 

     //Now you can use reflection or dynamic to call the method. I will show you the dynamic way 

     dynamic c = Activator.CreateInstance(class1Type); 
     c.Output(@"Hello"); 

     Console.ReadLine(); 
    } 
+0

非常感謝你 - 這正是我所期待的。我不敢相信這不會比其他答案的評分更高,因爲它顯示了動態關鍵字的使用。 – skiphoppy

+0

啊,現在我發現它也是在DarkFalcon的回答中。儘管如此,你的時間更短,更容易看到。 :) – skiphoppy

0

Activator.CreateInstance()返回一個對象,它沒有輸出方法。

它看起來像你來自動態編程語言? C#肯定不是那個,你正在努力做什麼將是困難的。

既然你是從一個特定的位置加載一個特定的DLL,也許你只是想添加它作爲您的控制檯應用程序的參考?

如果你絕對想通過Assembly.Load加載程序集,你將不得不通過反射去調用任何成員c

喜歡的東西type.GetMethod("Output").Invoke(c, null);應該這樣做。

-4

這並不困難。

您可以檢查已加載對象的可用函數,並且如果您找到了要查找的名稱,然後偵聽其預期參數(如果有)。如果這是您正在嘗試查找的調用,則使用MethodInfo對象的Invoke方法調用它。

另一種選擇是簡單地將外部對象構建到接口,並將加載的對象轉換爲該接口。如果成功,請本地調用該函數。

這是非常簡單的東西。

+0

哇,不知道爲什麼反對票。我有一個生產應用程序,就像過去12年一樣。 *聳聳肩* 任何人都需要一些代碼來做到這一點,射我一條消息。我將打包部分生產代碼併發送。 – ChrisH