C# 动态加载程序集信息
程序员文章站
2022-06-29 19:40:23
在设计模式的策略模式中,需要动态加载程序集信息,本文通过一个简单的实例,来讲解动态加载dll需要的知识点。
涉及知识点:
assemblyname类...
在设计模式的策略模式中,需要动态加载程序集信息,本文通过一个简单的实例,来讲解动态加载dll需要的知识点。
涉及知识点:
- assemblyname类,完整描述程序集的唯一标识, 用来表述一个程序集。
- assembly类,在system.reflection命名空间下,表示一个程序集,它是一个可重用、无版本冲突并且可自我描述的公共语言运行时应用程序构建基块。
- module类 表述在模块上执行反射,表述一个程序集的模块信息。
- type类,在system命名空间下,表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。
- fieldinfo类,发现字段属性并提供对字段元数据的访问权。
- methodinfo类,发现方法的属性并提供对方法元数据的访问。
- eventinfo类,发现事件的属性并提供对事件元数据的访问权。
- constructorinfo类,发现类构造函数的属性并提供对构造函数元数据的访问权。
- activator类,包含特定的方法,用以在本地或从远程创建对象类型,或获取对现有远程对象的引用。此类不能被继承。
- bindingflags类,指定控制绑定和由反射执行的成员和类型搜索方法的标志。在获取方法时,第二个参数会用到
如下图所示:
具体代码如下:
public partial class dllloadform : form { public dllloadform() { initializecomponent(); } private void btnopenfile_click(object sender, eventargs e) { openfiledialog ofd = new openfiledialog() { multiselect=false, filter = "dll info|*.dll|all files|*.*", initialdirectory=appdomain.currentdomain.basedirectory, title="dll信息", tag="请选择" }; if (ofd.showdialog() == dialogresult.ok) { this.txtdllfile.text = ofd.filename; } } private void btnloaddll_click(object sender, eventargs e) { if (string.isnullorempty(this.txtdllfile.text.trim())) { messagebox.show("请选择dll文件"); return; } loaddllinfo(this.txtdllfile.text); } /// <summary> /// 动态加载dll /// </summary> /// <param name="dllpath">需要加载的dll的路径</param> public void loaddllinfo(string dllpath) { if (file.exists(dllpath)) { treenodecollection tvnodes = tvdllinfo.nodes; tvnodes.clear(); tvnodes.add("dllinfo"); assemblyname dllassemblyname = assemblyname.getassemblyname(dllpath); assembly dllassembly = assembly.load(dllassemblyname); module[] modules = dllassembly.getmodules();//获取作为程序集一部分的所有模块信息 type[] types = dllassembly.gettypes();//获取程序集中定义的所有类型 assemblyname[] referrenceasseblies = dllassembly.getreferencedassemblies();//获取程序集引用的程序集信息 tvnodes[0].nodes.add("基本信息"); string dllfullname = dllassembly.fullname; bool isglobalasseblycache = dllassembly.globalassemblycache;//是否从全局程序集加载 bool isfulltrusted = dllassembly.isfullytrusted;//是否已完全信任方式加载的 module manifestmodule = dllassembly.manifestmodule;//获取清单模块 bool isreflectiononly = dllassembly.reflectiononly;//是否加载到只反射模块中 //更新到节点 tvnodes[0].nodes[0].nodes.add(string.format("全路径:{0}", dllfullname)); tvnodes[0].nodes[0].nodes.add(string.format("是否全局程序集:{0}", isglobalasseblycache)); tvnodes[0].nodes[0].nodes.add(string.format("是否全信任:{0}", isfulltrusted)); tvnodes[0].nodes[0].nodes.add(string.format("是否只反射:{0}", isreflectiononly)); tvnodes[0].nodes[0].nodes.add(string.format("清单模块:{0}", manifestmodule.name)); ienumerable<type> exportedtypes = dllassembly.exportedtypes;//公共类型集合 tvnodes[0].nodes.add("模块信息"); int i = 0; foreach (var module in modules) { fieldinfo[] fields = module.getfields();//返回模块中定义的全局字段 methodinfo[] methods = module.getmethods();//返回模块中定义的全局方法 type[] mtypes = module.gettypes();//返回模块中定义的类型集合 bool isresource = module.isresource();//指示此模块是否是资源 int mdstreamversion = module.mdstreamversion;//获取源数据流的版本 guid versionid = module.moduleversionid;//获取模块的版本id string modulename = module.name;//获取模块的名称,去除路径的 int metadatatoken = module.metadatatoken; string scopename = module.scopename; tvnodes[0].nodes[1].nodes.add(string.format("模块:{0}", modulename)); tvnodes[0].nodes[1].nodes[i].nodes.add(string.format("数据流版本:{0}", mdstreamversion)); tvnodes[0].nodes[1].nodes[i].nodes.add(string.format("是否资源:{0}", isresource)); tvnodes[0].nodes[1].nodes[i].nodes.add(string.format("版本id:{0}", versionid)); tvnodes[0].nodes[1].nodes[i].nodes.add(string.format("metadata:{0}", metadatatoken)); tvnodes[0].nodes[1].nodes[i].nodes.add(string.format("scopename:{0}", scopename)); tvnodes[0].nodes[1].nodes[i].nodes.add(getnodes<fieldinfo>(fields, "公共字段")); tvnodes[0].nodes[1].nodes[i].nodes.add(getnodes<methodinfo>(methods, "mehods")); //tvnodes[0].nodes[1].nodes[i].nodes.add(string.format("types:{0}", string.join(",", mtypes.select(p => p.name)))); i++; } tvnodes[0].nodes.add("类型信息"); i = 0; foreach (var type in types) { typeattributes typeattributes = type.attributes;//与type关联的属性 string typefullname = type.fullname;//获取类型的完全限定名称 fieldinfo[] typefields = type.getfields();//获取所有的公共字段 eventinfo[] typeevents = type.getevents();//获取所有的 公共事件 type[] typeinterfaces = type.getinterfaces();//获取所有的公共接口 memberinfo[] typemembers = type.getmembers();//获取所有的公共成员 methodinfo[] typemethods = type.getmethods();//获取所有的公共方法 typeinfo typeinfo = type.gettypeinfo();//返回指定类型的表述形式 string namespace = type.namespace; //指定类型的命名空间 string typename = type.name;//获取当前成员的名称 constructorinfo[] typeconstructors = type.getconstructors();//类型的构造函数 tvnodes[0].nodes[2].nodes.add(string.format("类型:{0}", typename)); tvnodes[0].nodes[2].nodes[i].nodes.add(string.format("全名称:{0}", typefullname)); tvnodes[0].nodes[2].nodes[i].nodes.add(string.format("制定类型名称:{0}", typeinfo.name)); tvnodes[0].nodes[2].nodes[i].nodes.add(string.format("命名空间:{0}", namespace)); tvnodes[0].nodes[2].nodes[i].nodes.add(string.format("接口:{0}", string.join(",", typeinterfaces.select(p => p.name)))); tvnodes[0].nodes[2].nodes[i].nodes.add(getnodes<fieldinfo>(typefields, "公共字段")); tvnodes[0].nodes[2].nodes[i].nodes.add(getnodes<constructorinfo>(typeconstructors, "构造函数")); tvnodes[0].nodes[2].nodes[i].nodes.add(getnodes<eventinfo>(typeevents, "事件")); tvnodes[0].nodes[2].nodes[i].nodes.add(getnodes<memberinfo>(typemembers, "成员member")); tvnodes[0].nodes[2].nodes[i].nodes.add(getnodes<methodinfo>(typemethods, "公共方法")); i++; } } } /// <summary> /// 通过类型获取节点 /// </summary> /// <typeparam name="t"></typeparam> /// <param name="lstinfos"></param> /// <param name="name"></param> /// <returns></returns> public treenode getnodes<t>(t[] lstinfos, string name) where t : memberinfo { treenode tnode = new treenode(name); foreach (var t in lstinfos) { tnode.nodes.add(t.name); } return tnode; } /// <summary> /// 调用静态方法的例子 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btncallstaticbyreflection_click(object sender, eventargs e) { assemblyname assemblyname = assemblyname.getassemblyname("testassembly.exe"); assembly assembly = assembly.load(assemblyname); type t = assembly.gettype("testassembly.program", true, true); //object o= activator.createinstance(t, false); methodinfo methodinfo = t.getmethod("main",bindingflags.static|bindingflags.public); methodinfo.invoke(null,new string[][] { new string[] { "g" } }); } /// <summary> /// 调用非静态方法的例子 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btncallfunctionbyreflection_click(object sender, eventargs e) { assemblyname assemblyname = assemblyname.getassemblyname("testassembly.exe");//此处是相对路径 assembly assembly = assembly.load(assemblyname); type t = assembly.gettype("testassembly.program", true, true); object o = activator.createinstance(t, false); methodinfo methodinfo = t.getmethod("testassembly", bindingflags.instance|bindingflags.public); object tmp= methodinfo.invoke(o,null); messagebox.show(tmp.tostring()); } }
动态加载和反射调用的功能还有很多,不能一一列举,只能在以后的工作中用到时再加以研究。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!