Home  >  Article  >  Backend Development  >  Detailed explanation of C# dynamically loaded assembly information (picture)

Detailed explanation of C# dynamically loaded assembly information (picture)

黄舟
黄舟Original
2017-03-16 13:18:252390browse

In the Strategy Mode of the Design Mode, assembly information needs to be dynamically loaded. This article uses a simple example to explain the requirements for dynamically loading Dll knowledge points. Let’s take a look with the editor below

In the strategy mode of the design mode, assembly information needs to be dynamically loaded. This article uses a simple example to explain the knowledge points required to dynamically load Dll.

Involved knowledge points:

  • AssemblyName class, which completely describes the unique identifier of the assembly and is used to express an assembly.

  • Assembly class, under the System.Reflection namespace, represents an assembly, which is a reusable, version-conflict-free and self-describing common language Runtime application building blocks.

  • Module class expresses the execution of reflection on the module and expresses the module information of an assembly.

  • Type class, under the System namespace, represents type declaration: class type, interface type, arraytype, value type, enumeration Example types, type parameters, generic type definitions, and open or closed constructed generic types.

  • FieldInfo class, discovers field properties and provides access to field metadata.

  • MethodInfo class, discovers the properties of a method and provides access to method metadata.

  • EventInfo class, discovers properties of events and provides access to event metadata.

  • ConstructorInfo class, discovers properties of class Constructor and provides access to constructor metadata.

  • Activator class, contains specific methods to create objects types locally or from a remote , or to obtain a reference to an existing remote object. This class cannot be inherited.

  • BindingFlags class, specifies flags that control binding and members and types search methods executed by reflection. When obtaining the method, the second parameter will be used

as shown in the figure below:

The specific code is as follows:


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

There are many more functions of dynamic loading and reflection calling, which cannot be listed one by one. They can only be studied when they are used in future work.

The above is the detailed content of Detailed explanation of C# dynamically loaded assembly information (picture). For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn