Maison >développement back-end >Tutoriel C#.Net >Explication détaillée des informations d'assemblage chargées dynamiquement en C# (image)

Explication détaillée des informations d'assemblage chargées dynamiquement en C# (image)

黄舟
黄舟original
2017-03-16 13:18:252464parcourir

Dans le Mode Stratégie du Mode Conception, il est nécessaire de charger dynamiquement les informations d'assemblage. Cet article utilise un exemple simple pour expliquer les exigences pour le chargement dynamique de Dl. l points de connaissances. Jetons un coup d'œil avec l'éditeur ci-dessous

Dans le mode stratégie du mode conception, les informations d'assemblage doivent être chargées dynamiquement. Cet article utilise un exemple simple pour expliquer les points de connaissances requis pour charger dynamiquement la DLL.

Implique des points de connaissance :

  • Classe AssemblyName, qui décrit entièrement l'identifiant unique de l'assembly et est utilisée pour exprimer un assembly. La classe

  • Assembly, sous l'espace de noms System.Reflection , représente un assembly, qui est un runtime de langage commun réutilisable, sans conflit de versions et auto-descriptif. éléments constitutifs des applications. La classe

  • Module exprime l'exécution d'une réflexion sur le module et exprime les informations de module d'un assemblage.

  • La classe Type, sous l'espace de noms System, représente la déclaration de type : type de classe, interfacetype, arraytype, type de valeur, énumération Exemple types, paramètres de type, définitions de types génériques et types génériques construits ouverts ou fermés.

  • Classe FieldInfo, découvre les propriétés du champ et donne accès aux métadonnées du champ.

  • Classe MethodInfo, découvre les propriétés d'une méthode et donne accès aux métadonnées de la méthode. La classe

  • EventInfo découvre les propriétés de l'event et donne accès aux métadonnées de l'événement.

  • Classe ConstructorInfo, découvre les propriétés de la classe constructeur et donne accès aux métadonnées du constructeur.

  • Classe Activateur, contenant des méthodes spécifiques pour créer des objets de type localement ou à distance , ou pour obtenir des références à des objets distants existants. Cette classe ne peut pas être héritée.

  • Classe BindingFlags, spécifie les indicateurs qui contrôlent la liaison et les membres et types exécutés par réflexion Recherche de méthodes. Lors de l'obtention de la méthode, le deuxième paramètre sera utilisé

comme indiqué dans la figure ci-dessous :

Le code spécifique est le suivant suit :


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

Il existe de nombreuses autres fonctions de chargement dynamique et d'appel de réflexion, qui ne peuvent pas être répertoriées une par une. Elles ne peuvent être étudiées que lorsqu'elles sont utilisées dans. travaux futurs.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn