当前位置:主页 > 软件编程 > .NET代码 >

C# 动态加载程序集信息

时间:2020-12-26 12:45:40 | 栏目:.NET代码 | 点击:

 在设计模式的策略模式中,需要动态加载程序集信息,本文通过一个简单的实例,来讲解动态加载Dll需要的知识点。

涉及知识点:

如下图所示:

具体代码如下:

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());
    }
  }

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

您可能感兴趣的文章:

相关文章