加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

如何动态加载DLL并在其中使用一个类(实现一个已知的接口)[C#]

发布时间:2020-12-14 01:54:22 所属栏目:Windows 来源:网络整理
导读:假设我有3个DLL(BlueCar,RedCar,YellowCar),每个DLL都有一个命名类(BlueCarClass等),它们都实现了相同的接口Car,并且都是从同一个命名空间(Car_Choices)构建的.所以DLL在编译之前看起来像这样: namespace Car_Choices{ public interface Car { void What_Co
假设我有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.

PROJECT 2:Car接口实现,作为类库
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程序集中的Car类可能具有完全限定名称

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

但是你的应用程序中的Car类具有不同的完全限定名称,就像这样

SomeApp.Car,SomeApp,PublicKey = null

即使您将类放在同一名称空间中,全名仍然不同,因为它包含程序集名称.

有多种方法可以实现您想要的结果:您可以使用MEF,或者您可以自己创建更轻量级的东西.

您的解决方案需要至少有3个程序集:

>接口库.这保持了ICar界面.
>插件库. (在你的情况下,RedCar等).它引用了#1库.
>申请.它显式引用库#1并动态使用#2.

PS实际上你可以通过合并#1和#3使用2个程序集来做到这一点,并使#2引用#3而不是#1.它会起作用,但它在逻辑上是不正确的,因为你引入了交叉引用(隐式).在我看来,这种方法闻起来.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读