c#动态加载dll并调用dll中类的方法

时间:2021-11-28 04:37:18

当然,这里指的是托管的dll与托管的方法,实际上用到的东西大部分是在反射(reflecting)命名空间里头的。
用途或许广泛吧,我不是很确信,但这个是在运行期绑定的,那么就不会有编译期绑定那么僵硬……但也没有编译期绑定那么简单。
可以用于做插件之类的。
先是一个接口,实现了这个接口的类被认为是合法的,可以被载入的……

namespace gp
{
    public delegate void DoWhat();
    public interface IInterface
    {
        string GetName();
        DoWhat dowhat { get; set; }
    }
}

很简单的接口,一个是用于判断做什么的函数,另外一个,则是一个方法的委托,做什么。
然后,我们新建一个项目,弄个类实现这个接口:

 

namespace gp
{
    public delegate void DoWhat();
    public interface IInterface
    {
        string GetName();
        DoWhat dowhat { get; set; }
    }
}

在构造函数里头将委托加了一个项,当执行那个委托的时候就会执行这个函数。
现在是重要的一个部分,代码难度不大~~
新建一个windows application,然后在窗体上头拖一个panel,这个是为了动态加载后将操作按钮放上去的。。不过可能会重叠,建议考虑用flowlayoutpanel,这个会自动重排以满足个数,anyway,无所谓,反正是为了阐述概念。

        private void Form1_Load(object sender, EventArgs e)
        {
            var plugindir = System.IO.Directory.GetParent(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName).CreateSubdirectory("startup");
            foreach (var filesInPlugin in plugindir.GetFiles())
            {
                if (filesInPlugin.Extension.ToLower() == ".dll")
                {
                    Assembly dllFromPlugin = Assembly.LoadFile(filesInPlugin.FullName);
                    foreach (var dllModule in dllFromPlugin.GetLoadedModules())
                    {
                        foreach (var typeDefinedInModule in dllModule.GetTypes())
                        {
                            if (typeDefinedInModule.GetInterfaces().Contains(typeof(gp.IInterface)))
                            {
                                if (typeDefinedInModule.IsClass)
                                {
                                    var itemGet = System.Activator.CreateInstance(typeDefinedInModule) as gp.IInterface;
                                    LinkLabel ll_now = new LinkLabel();
                                    ll_now.Text = itemGet.GetName();
                                    ll_now.Click += (a, b) => { if (itemGet.dowhat != null)itemGet.dowhat(); };
                                    panel1.Controls.Add(ll_now);
                                }
                            }
                        }
                    }
                }
            }
        }

一个不难看懂的代码,先是指定插件文件夹的位置,要是没有就创建一个。然后遍历里头为dll类型的文件,再试图转载这个文件——实际情况下,这里需要加 try...catch,因为谁也不知道你加载的dll文件倒是是不是合法的dll文件,然后遍历里头的模块,再遍历模块里头的定义的类型——可能是类、 interface、枚举等等等等,很多很多,取得这个玩意儿的集成的interface,再判断是不是包含我们的interface。(也就是说,包含了这个interface就算是合法的插件类)
如果包含了的话,判断这是不是一个类,因为接口也可以在其他的东西里头被继承,比如另一个接口等等,而其他这些情况对我们来说毫无意义。
然后,我们动态创建这个类的实例—— System.Activator.CreateInstance,并且进行转换,转换为继承的接口,现在开始就是强类型操作了。我这里做的操作是生成一个linklabel,并且设置名称和按下执行的方法。。。大概就是这样,以上。