簡體   English   中英

在 C# 中在運行時加載 DLL

[英]Loading DLLs at runtime in C#

我想弄清楚如何在 C# 應用程序中在運行時導入和使用 .dll。 使用 Assembly.LoadFile() 我已經設法讓我的程序加載 dll(這部分肯定有效,因為我能夠使用 ToString() 獲取類的名稱),但是我無法使用“輸出”我的控制台應用程序中的方法。 我正在編譯 .dll,然后將其移動到我的控制台項目中。 在 CreateInstance 和能夠使用這些方法之間是否有額外的步驟?

這是我的 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();
        }
    }
}

成員必須在編譯時可解析才能直接從 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();
        }
    }
}

現在,您正在為程序集中定義每個類型創建一個實例。 您只需要創建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();
    }
}

您需要創建一個公開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();
     }

Activator.CreateInstance()返回一個對象,該對象沒有 Output 方法。

看起來你來自動態編程語言? C# 絕對不是那樣,你想要做的事情會很困難。

由於您是從特定位置加載特定 dll,也許您只想將其添加為對您的控制台應用程序的引用?

如果您絕對想通過Assembly.Load加載程序Assembly.Load ,則必須通過反射調用c任何成員

類似於type.GetMethod("Output").Invoke(c, null); 應該這樣做。

foreach (var f in Directory.GetFiles(".", "*.dll"))
            Assembly.LoadFrom(f);

這會加載可執行文件文件夾中的所有 DLL。

就我而言,我試圖使用Reflection來查找一個類的所有子類,即使在其他 DLL 中也是如此。 這有效,但我不確定這是否是最好的方法。

編輯:我計時,它似乎只在第一次加載它們。

Stopwatch stopwatch = new Stopwatch();
for (int i = 0; i < 4; i++)
{
    stopwatch.Restart();
    foreach (var f in Directory.GetFiles(".", "*.dll"))
        Assembly.LoadFrom(f);
    stopwatch.Stop();
    Console.WriteLine(stopwatch.ElapsedMilliseconds);
}

輸出:34 0 0 0

因此,為了以防萬一,可以在任何反射搜索之前運行該代碼。

這不是那么困難。

您可以檢查已加載對象的可用功能,如果您按名稱找到了您要查找的功能,則窺探其預期參數(如果有)。 如果是您要查找的調用,則使用 MethodInfo 對象的 Invoke 方法調用它。

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

這是很簡單的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM