Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung des grafischen Codes der C#-Assemblierung und -Reflexion

Detaillierte Erläuterung des grafischen Codes der C#-Assemblierung und -Reflexion

黄舟
黄舟Original
2017-03-29 11:45:381881Durchsuche

In diesem Artikel wird hauptsächlich das Wissen über C#-Assembly und -Reflexion vorgestellt. Es hat einen gewissen Referenzwert, schauen wir es uns mit dem Herausgeber unten an

Hier möchte ich noch ein paar Worte sagen. Jeder fühlt sich sehr glücklich, wenn er lernt, beispielsweise Bücher liest oder Videos ansieht Sie haben im Grunde das Gefühl, zuzuschauen. Es ist tatsächlich eine Sache, es selbst zu verstehen. Sie sollten sich das Gelernte zu eigen machen, anstatt andere zu kopieren.

Bevor wir über Reflexion sprechen, wollen wir zunächst verstehen, was eine Versammlung ist.

Assembly

Assembly ist ein Konzept in .net. Eine Assembly kann als Paket für eine Reihe verwandter Klassen angesehen werden, was dem Jar in Java entspricht. Tasche.

Assemblys enthalten:

  • Ressourcendateien

  • Typmetadaten (Beschreibung jedes Typs und jeder Mitglieder, binäre Form)

  • IL-Code (diese sind in exe oder dll gekapselt)

Der Unterschied zwischen exe und dll.

exe kann ausgeführt werden, dll kann jedoch nicht direkt ausgeführt werden, da es in exe eine Hauptfunktion (Eingabefunktion) gibt.

Typ-Metadaten Diese Informationen können über die Datei AssemblyInfo.cs angepasst werden. In jedem .net-Projekt gibt es eine AssemblyInfo.cs-Datei. Das Codeformat ist:

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("ReflectedDemo")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ReflectedDemo")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("7674d229-9929-4ec8-b543-4d05c6500863")]
// 程序集的版本信息由下面四个值组成: 
//
//   主版本
//   次版本 
//   生成号
//   修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”: 
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Wo werden diese Informationen wiedergegeben? Dies spiegelt sich in den Eigenschaften unserer Assembly wider.

Wenn wir normalerweise einige CS-Client-Programme

installieren, werden wir viele Assemblydateien im Installationsverzeichnis sehen.

Vorteile der Verwendung von Assemblys

  • Nur ​​die notwendigen Assemblys werden im Programm referenziert, wodurch die Größe des Programms reduziert wird.

  • Assemblys können einen Teil des Codes kapseln und nur die notwendigen Zugriffsschnittstellen bereitstellen.

  • Einfach zu erweitern.

Wie füge ich einer Baugruppe einen Verweis hinzu?

Fügen Sie den Assembly-Pfad direkt hinzu oder fügen Sie einen Projektverweis in der Lösung hinzu.

Wenn wir ein Programm erweitern müssen, können Sie es direkt zum Originalprojekt hinzufügen. Was ist in diesem Fall, wenn Sie Ihren Code mit anderen teilen möchten? Sie können es in eine Assembly packen und andere können es dann erweitern, indem sie auf Ihre Assembly verweisen. Wie unsere gängigen .net-

Framework-Bibliotheken von Drittanbietern, wie log4net, Unity usw.

Hinweis: Sie können keinen Zirkelverweis hinzufügen.

Was bedeutet das Hinzufügen eines Zirkelverweises? Das heißt, wenn Projekt A einen Projektverweis zu Projekt B hinzufügt, kann Projekt B zu diesem Zeitpunkt keinen Projektverweis zu Projekt A hinzufügen. Das heißt, wenn ein Projektverweis hinzugefügt wird, muss dies unidirektional sein unser gemeinsames dreistufiges Projektreferenzen.

Reflexion

Was die Reflexion betrifft: Solange Sie .net entwickeln, werden Sie es auf jeden Fall jeden Tag verwenden. Da die intelligenten Eingabeaufforderungen von VS durch die Anwendung der Reflection-Technologie sowie unseres häufig verwendeten Dekompilierungsartefakts Reflector.exe implementiert werden, können Sie dies am Namen erkennen. In Projekten kommt es häufiger vor, Objekte dynamisch zu instanziieren, indem Konfigurationsdateien kombiniert werden, z. B. durch das Wechseln von Datenbankinstanzen oder durch die Abhängigkeitsinjektion von Sprint.net über Konfigurationsdateien.

Reflection-Technologie ist eigentlich die Funktion, die Metadaten einer Assembly dynamisch abzurufen, die DLL dynamisch zu laden und sie dann zu analysieren, um Objekte zu erstellen und Mitglieder aufzurufen.

Type ist eine Beschreibung der Klasse. Die Type-Klasse ist eine wichtige Klasse für die Implementierung der Reflexion. Dadurch können wir alle Informationen in der Klasse erhalten, einschließlich Methoden, Attribute usw. Eigenschaften und Methoden von Klassen können dynamisch aufgerufen werden.

Das Aufkommen der Reflexion hat die Art und Weise, Objekte zu schaffen, verändert, denn in der Vergangenheit wurden Objekte direkt durch Neues geschaffen.

Die DLL besteht aus zwei Teilen: der IL-Zwischensprache und den Metadatenelementdaten.

Der

Namespace , der für Reflektion in .NET verwendet wird, ist System.Reflection. Hier werde ich zunächst eine Demo verwenden, um zu sehen, was Reflektion bewirken kann

1. Erstellen Sie eine neue Konsole Projekt ReflectedDemo

2. Erstellen Sie eine neue

KlassenbibliothekProjekt My.Sqlserver.Dal

Erstellen Sie zwei neue Klassen, SqlServerHelper und SqlCmd, die erstere ist eine öffentliche Klasse und die Letzteres ist eine private Klasse

namespace My.Sqlserver.Dal
{
  public class SqlServerHelper
  {
    private int age = 16;
    public string Name { get; set; }
    public string Query()
    {
      return string.Empty;
    }
  }
  class SqlCmd
  {
  }
}
3. Projekt ReflectedDemo, fügen Sie die Projektreferenz von My.Sqlserver.Dal hinzu. Der Zweck besteht darin, die Existenz der My.Sqlserver.Dal.dll-Assembly zu erleichtern das bin-Verzeichnis im Projekt ReflectedDemo.

using System;
using System.Reflection;
namespace ReflectedDemo
{
  class Program
  {
    static void Main(string[] args)
    {
      //加载程序集文件,在bin目录中查找
      Assembly assembly = Assembly.Load("My.Sqlserver.Dal");
      Console.WriteLine("----------------Modules----------------------");
      var modules = assembly.GetModules();
      foreach(var module in modules)
      {
        Console.WriteLine(module.Name);
      }
      Console.WriteLine("----------------Types----------------------");
      var types = assembly.GetTypes(); //获取程序集中所有的类型,包括公开的和不公开的
      foreach(var type in types)
      {
        Console.WriteLine(type.Name);
        Console.WriteLine(type.FullName);
        var members= type.GetMembers(); //获取Type中所有的公共成员
        Console.WriteLine("----------------members----------------------");
        foreach(var m in members)
        {
          Console.WriteLine(m.Name);
        }
      }
      Console.WriteLine("----------------GetExportedTypes----------------------");
      var exportedTypes = assembly.GetExportedTypes(); //获取程序集中所有的公共类型
      foreach(var t in exportedTypes)
      {
        Console.WriteLine(t.Name);
      }
      Console.WriteLine("----------------GetType----------------------");
      var typeName= assembly.GetType("SqlServerHelper");//获取程序集中指定名称的类型对象
      Console.WriteLine(typeName.Name);
    }
  }
}

Objekte dynamisch erstellen

通过ass.CreateInstance(string typeName) 和Activator.CreateInstance(Type t)方法

他们之间的区别

ass.CreateInstance(string typeName) 会动态调用类的无参构造函数创建一个对象,返回值就是创建的对象,如果没有无参构造函数就会报错。


Assembly assembly = Assembly.Load("My.Sqlserver.Dal");
object obj = assembly.CreateInstance("My.Sqlserver.Dal.SqlServerHelper");
Console.WriteLine(obj.GetType().ToString());

如果我们来修改SqlServerHelper类的代码,添加如下构造函数:

    public SqlServerHelper(int age)
    {
      this.age = age;
    }

这个时候再来运行创建实例的代码就会报错了,而编译时是不报错的。

所以我们一般推荐使用Activator.CreateInstance方法来创建反射对象,因为此方法有许多重载,支持将参数传递给构造函数。

此时再调用就不会出现异常了。

Type类中有三个用得比较多的方法:

  • bool IsAssignableFrom(Type t):是否可以从t赋值,判断当前的类型变量是不是可以接受t类型变量的赋值。

  • bool IsInstanceOfType(object o):判断对象o是否是当前类的实例,当前类可以是o的类、父类、接口

  • bool IsSubclassOf(Type t):判断当前类是否是t的子类

Type类中还有一个IsAbstract属性:判断是否为抽象的,包含接口。

它们常用的原因是我们通过反射可以取到的东西太多了,我们需要对数据进行过滤。

添加类BaseSql,让类SqlServerHelper继承自BaseSql

然后查看调用代码:

      bool result = typeof(BaseSql).IsAssignableFrom(typeof(SqlServerHelper));
      Console.WriteLine(result);


   SqlServerHelper _SqlServerHelper = new SqlServerHelper(1);
   bool result = typeof(SqlServerHelper).IsInstanceOfType(_SqlServerHelper);
   Console.WriteLine(result);


      SqlServerHelper _SqlServerHelper = new SqlServerHelper(1);
      bool result = typeof(SqlServerHelper).IsSubclassOf(typeof(BaseSql));
      Console.WriteLine(result);

项目中常用的利用反射来动态切换数据库Demo:

新建类库项目My.Sql.IDal,并添加接口ISqlHelper。通过接口来实现数据库操作的类的解耦,因为接口是抽象的。

  public interface ISqlHelper
  {
    string Query();
  }

添加类库项目My.MySql.Dal,并新增类MySqlHelper.cs

My.Sqlserver.Dal、My.MySql.Dal项目分别添加对项目My.Sql.IDal的引用。让SqlServerHelper继承自接口ISqlHelper

public class MySqlHelper : ISqlHelper
  {
    public string Query()
    {
       return this.GetType().ToString();
    }
  }
  public class SqlServerHelper :ISqlHelper
  {
    private int age = 16;
    public string Name { get; set; }
    public string Query()
    {
      return this.GetType().ToString();
    }
  }

添加App.config配置项

 <appSettings>
  <add key="DBName" value="My.Sqlserver.Dal,SqlServerHelper"/>
 </appSettings>

ReflectedDemo项目中Program.cs调用代码:

string str = ConfigurationManager.AppSettings["DBName"];
      string strAssembly = str.Split(&#39;,&#39;)[0];
      string strClass=str.Split(&#39;,&#39;)[1];
      Assembly assembly = Assembly.Load(strAssembly);
      Type t = assembly.GetType(strAssembly + "." + strClass);
      ISqlHelper obj = Activator.CreateInstance(t) as ISqlHelper;
      Console.WriteLine(obj.Query());

这样每次需要切换数据库时,只要修改配置文件就可以了。

项目结构:

注意:反射虽然很强大,但却是比较耗性能的,所以一般和缓存结合起来使用。

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des grafischen Codes der C#-Assemblierung und -Reflexion. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn