簡體   English   中英

如何動態加載DLL並在其中使用類(實現已知接口)[C#]

[英]How to dynamically load a DLL and use a class in it (that implements a known interface) [C#]

假設我有3個DLL(BlueCar,RedCar,YellowCar),每個DLL都有一個命名類(BlueCarClass等),它們也都實現了相同的接口Car,並且都是從相同的命名空間(Car_Choices)構建的。 因此,DLL在編譯之前看起來像這樣:

namespace Car_Choices
{
    public interface Car
    {
        void What_Color();
    }

    public class BlueCarClass : Car
    {
        public void What_Color()
        {
            MessageBox.Show('The color is blue.');
        }
    }
}

DLL的名稱將為“ BlueCar.dll”。

在主程序中,用戶選擇他們想要的汽車顏色,並根據其選擇僅動態加載適當的DLL並運行What_Color()。 主程序具有Car接口的副本。 現在,我有以下內容,但是它不起作用。

static void Main()
{
    string car_choice = win_form_list.ToArray()[0]; //gets choice from a drop down
    Assembly car_assembly = Assembly.Load(car_choice); //car_choice is BlueCar
    Type car_type = car_assembly.GetType("Car");
    Car car = Activator.CreateInstance(type) as Car;
    car.What_Color();
}

我也嘗試過

static void Main()
{
    string car_choice = win_form_list.ToArray()[0]; //gets choice from a drop down
    ObjectHandle car_handle = Activator.CreateInstance(assembly_name, "Car_Choices."+ car_choice);
    Car car= (Car)handle.Unwrap();
    car.What_Color();
}

有什么幫助嗎? 我是否需要進行結構上的更改(例如將每個汽車顏色DLL放入其自己的名稱空間中)? 還是我不了解如何從DLL中正確加載和使用類。

編輯:這是我必須使用的解決方案,以防有人在尋找更詳細的答案。

項目1:共享接口(作為類庫)Car_Interface.cs

namespace Car_Interface
{
    public interface ICar_Interface
    {
        char Start_Car();
    }
}

編譯為Car_Interface.dll,在接下來的2個項目中引用DLL。

項目2:汽車接口實現,作為類庫BlueCar.cs

namespace BlueCar_PlugIn
{
    public class BlueCar : Car_Interface.ICar_Interface
    {
        public char Start_Car()
        {
            MessageBox.Show("Car is started");
        }
    }
}

編譯成BlueCar_PlugIn.dll

項目3:主程序/驅動程序Program.cs

namespace Main_Program
{
    public class Program
    {
        static void Main()
        {
            Assembly assembly = Assembly.Load(DLL_name); //Where DLL_name is the DLL you want to load, such as BlueCar_PlugIn.dll
            Type type = (Type)assembly.GetTypes().GetValue(0); //Class that implements the interface should be first. A resource type could also possibly be found
            //OR
            Type type = (Type)assembly.GetType(DLL_name + class_name); //In this case, BlueCar_PlugIn.BlueCar
            Car_Interface.ICar_Interface new_car = (Car_Interface.ICar_Interface)Activator.CreateInstance(type);
            new_car.Start_Car();
        }
    }
}

現在,如果將兩個DLL都移到bin(或將程序編譯到的任何位置)中並運行它,它將能夠動態加載BlueCar_PlugIn.dll,但不必運行它(例如,如果您有YellowCar_PlugIn.dll和也具有類似實現的RedCar_PlugIn.dll,只需加載一個程序即可運行。

您的代碼不起作用,因為例如, BlueCarClass不實現應用程序程序集中的Car ,因為基類的完全限定名稱不同。 BlueCar裝配中的Class Car可能具有完全合格的名稱

BlueCar.Car,BlueCar,版本= 1.0.0.0,文化=中性,公鑰=空

但是您的應用程序中的Car類具有不同的完全限定名稱,例如:

SomeApp.Car,SomeApp,Version = 1.0.0.0,Culture = neutral,PublicKey = null

即使將類放在相同的名稱空間中,全名仍然是不同的,因為它包含程序集名稱。

有多種方法可以實現所需的結果:可以使用MEF ,也可以自己創建更輕量的內容。

您的解決方案至少需要3個程序集:

  1. 接口庫。 保留ICar接口。
  2. 插件庫。 (在您的情況下為BlueCar,RedCar等)。 它引用了庫#1。
  3. 應用。 它顯式引用庫1,並動態使用庫2。

PS實際上,您可以通過合並#1和#3並使用#2引用#3而不是#1來使用2個程序集來執行此操作。 它將起作用,但是由於在邏輯上不正確,因為您引入了交叉引用。 我認為這種方法很香。

暫無
暫無

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

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