当前位置: 移动技术网 > IT编程>开发语言>c# > C# 动态加载程序集信息

C# 动态加载程序集信息

2019年07月18日  | 移动技术网IT编程  | 我要评论

 在设计模式的策略模式中,需要动态加载程序集信息,本文通过一个简单的实例,来讲解动态加载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());
    }
  }

动态加载和反射调用的功能还有很多,不能一一列举,只能在以后的工作中用到时再加以研究。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持移动技术网!

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网