ホームページ  >  記事  >  バックエンド開発  >  C#リフレクション技術コンセプトの機能とポイント

C#リフレクション技術コンセプトの機能とポイント

Y2J
Y2Jオリジナル
2017-04-17 16:45:581237ブラウズ

リフレクションは、.NET の重要なメカニズムです。放射を通じて、.NET のすべての型 (クラス、構造体、デリゲートなどを含む) を実行時に取得できます。 .html" target="_blank">プロパティイベントコンストラクターなどを含む)。各メンバーの名前を取得することもできます。 , 修飾子やパラメータなど。コンストラクターの情報を取得すれば、コンパイル時にオブジェクトの型が分からなくても、直接オブジェクトを作成できます。 .NET 実行可能アプリケーションの構造 プログラム コードは、コンパイル後に実行可能アプリケーションを生成します。まず、この実行可能アプリケーションの構造を理解する必要があります
アプリケーションの構造は、アプリケーション ドメイン - アセンブリ - モジュール - いくつかのレベルのメンバーに分かれています。共通言語ランタイム ローダーは、アプリケーション ドメインを管理します。この管理には、各アセンブリを対応するアプリケーション ドメインにロードすることと、各アセンブリ内の型階層のメモリ レイアウトを制御することが含まれます
アセンブリにはモジュールが含まれ、モジュールには型が含まれ、型にはメンバーが含まれます。リフレクションは、アセンブリ、モジュール、および型をカプセル化するオブジェクトを提供します。リフレクションを使用すると、型のインスタンスを動的に作成し、型を既存のオブジェクトまたは型にバインドし、その型のメソッドを呼び出したり、そのフィールドやプロパティにアクセスしたりできます。

(1) Assembly を使用してアセンブリを定義して読み込み、アセンブリ マニフェストにリストされているモジュールを読み込み、型を見つけてこのアセンブリから型のインスタンスを作成します

(2)
Module
を使用して、モジュールとモジュール内のクラスなどを含むアセンブリ。また、モジュールに定義されているすべてのグローバル メソッドまたは他の特定のメソッドを取得することもできます。

(3) ConstructorInfo を使用して、名前、パラメーター、アクセスを理解します。コンストラクターの修飾子 (pulic など) またはプライベート)および実装の詳細(抽象または仮想など)など。 Type の GetConstructors または GetConstructor メソッドを使用して、特定のコンストラクターを呼び出します。

(4) MethodInfo を使用して、メソッドの名前、戻り値の型、パラメーター、アクセス修飾子 (pulic または private など)、実装の詳細 (abstract または virtual など) などを理解します。 Type の GetMethods または GetMethod メソッドを使用して、特定のメソッドを呼び出します。 (5) FiedInfo を使用して、フィールドの名前、アクセス修飾子 (public または private など)、実装の詳細 (
static
など) などを理解し、フィールドの値を取得または設定します。

(6) EventInfo を使用して、イベントの名前、
イベント ハンドラー
プログラムデータ型、カスタム プロパティ、宣言型とリフレクション型などを理解し、イベント
ハンドラーを追加または
削除します。 (7) PropertyInfo を使用して、属性の名前、データ型、宣言型、反映型、読み取り専用か書き込み可能状態を理解し、属性値を取得または設定します。 (8) ParameterInfoを使用して、パラメータ名、データ型、入力パラメータか出力パラメータか、メソッドシグネチャ内のパラメータの位置などを理解します。

System.Reflection.Emit 名前空間 のクラスは、実行時に型を構築できる特別な形式のリフレクションを提供します。

リフレクションは、ユーザーがタイプを選択し、選択したタイプに関する情報を表示できるタイプ ブラウザと呼ばれるアプリケーションの作成にも使用できます。

さらに、Jscript などの言語コンパイラーは、リフレクションを使用してシンボル テーブルを構築します。 System.Runtime.Serialization 名前空間のクラスは、リフレクションを使用してデータにアクセスし、保持するフィールドを決定します。また、System.Runtime.Remoting 名前空間のクラスは、シリアル化を通じて間接的にリフレクションを使用します。 rreeeコードをコピー

3、在设计模式实现中使用反射技术

  采用反射技术可以简化工厂的实现。

  (1)工厂方法:通过反射可以将需要实现的子类名称传递给工厂方法,这样无须在子类中实现类的实例化。

  (2)抽象工厂:使用反射可以减少抽象工厂的子类。

  采用反射技术可以简化工厂代码的复杂程度,在.NET项目中,采用反射技术的工厂已经基本代替了工厂方法。

  采用反射技术可以极大地简化对象的生成,对以下设计模式的实现也有很大影响。

  (1)命令模式:可以采用命令的类型名称作为参数直接获得命令的实例,并且可以动态执行命令。

  (2)享元模式:采用反射技术实例化享元可以简化享元工厂。
4.  

反射的概述  

   反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等,。System.reflection命名空间包含的几个类,允许你反射(解析)这些元数据表的代码
   和反射相关的命名空间(我们就是通过这几个命名空间访问反射信息):   
   System.Reflection.MemberInfo   
    System.Reflection.EventInfo   
    System.Reflection.FieldInfo   
    System.Reflection.MethodBase   
    System.Reflection.ConstructorInfo   
    System.Reflection.MethodInfo   
    System.Reflection.PropertyInfo   
    System.Type   
    System.Reflection.Assembly   

   反射的层次模型:   
   
   注:层次间都是一对多的关系   

   反射的作用:   
   1. 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现 有对象中获取类型   
   2. 应用程序需要在运行时从某个特定的程序集中载入一个特定的类型,以便实现某个任务时可以用到反射。   
   3. 反射主要应用与类库,这些类库需要知道一个类型的定义,以便提供更多的功能。   

   应用要点:   
   1. 现实应用程序中很少有应用程序需要使用反射类型   
   2. 使用反射动态绑定需要牺牲性能   
   3. 有些元数据信息是不能通过反射获取的   
   4. 某些反射类型是专门为那些clr 开发编译器的开发使用的,所以你要意识到不是所有的反射类型都是适合每个人的。
   
   反射appDomain 的程序集   
    当你需要反射AppDomain 中包含的所有程序集,示例如下:
   

static void Main    
    {    
    //通过GetAssemblies 调用appDomain的所有程序集    
   foreach (Assembly assem in Appdomain.currentDomain.GetAssemblies())    
   {    
    //反射当前程序集的信息    
    reflector.ReflectOnAssembly(assem)    
   }    
  }

   
   说明:调用AppDomain 对象的GetAssemblies 方法 将返回一个由System.Reflection.Assembly元素组成的数组。   
   反射单个程序集   
   上面的方法讲的是反射AppDomain的所有程序集,我们可以显示的调用其中的一个程序集,system.reflecton.assembly 类型提供了下面三种方法:
  
   1. Load 方法:极力推荐的一种方法,Load 方法带有一个程序集标志并载入它,Load 将引起CLR把策略应用到程序集上,先后在全局程序集缓冲区,应用程序基目录和私有路径下面查找该程序集,如果找不到该程序集系统抛出异常   

   2. LoadFrom 方法:传递一个程序集文件的路径名(包括扩展名),CLR会载入您指定的这个程序集,传递的这个参数不能包含任何关于版本号的信息,区域性,和公钥信息,如果在指定路径找不到程序集抛出异常。   

   3. LoadWithPartialName:永远不要使用这个方法,因为应用程序不能确定再在载入的程序集的版本。该方法的唯一用途是帮助那些在.Net框架的测试环节使用.net 框架提供的某种行为的客户,这个方法将最终被抛弃不用。   
   注意:system.AppDomain 也提供了一种Load 方法,他和Assembly的静态Load 方法不一样,AppDomain的load 方法是一种实例方法,返回的是一个对程序集的引用,Assembly的静态Load 方发将程序集按值封装发回给发出调用的AppDomain.尽量避免使用AppDomain的load 方法      

   利用反射获取类型信息   

   前面讲完了关于程序集的反射,下面在讲一下反射层次模型中的第三个层次,类型反射   
   一个简单的利用反射获取类型信息的例子:   
   

using system;    
2    using sytem.reflection;    
3    class reflecting    
4    {    
5     static void Main(string[]args)    
6    {    
7     reflecting reflect=new reflecting();//定义一个新的自身类    
8     //调用一个reflecting.exe程序集    
9     assembly myAssembly =assembly.loadfrom(“reflecting.exe”)    
10     reflect.getreflectioninfo(myAssembly);//获取反射信息    
11    }   
12    //定义一个获取反射内容的方法    
13    void getreflectioninfo(assembly myassembly)    
14    {    
15     type[] typearr=myassemby.Gettypes();//获取类型    
16     foreach (type type in typearr)//针对每个类型获取详细信息   
17     {    
18     //获取类型的结构信息     http://www.cnblogs.com/sosoft/
19     constructorinfo[] myconstructors=type.GetConstructors;    
20     //获取类型的字段信息   
21     fieldinfo[] myfields=type.GetFiedls()    
22     //获取方法信息    
23     MethodInfo myMethodInfo=type.GetMethods();    
24     //获取属性信息    
25     propertyInfo[] myproperties=type.GetProperties    
26     //获取事件信息    
27     EventInfo[] Myevents=type.GetEvents;   
28    }    
29   }    
30 }

复制代码

   其它几种获取type对象的方法: 
   1. System.type 参数为字符串类型,该字符串必须指定类型的完整名称(包括其命名空间)   
   2. System.type 提供了两个实例方法:GetNestedType,GetNestedTypes   
   3. Syetem.Reflection.Assembly 类型提供的实例方法是:GetType,GetTypes,GetExporedTypes   
   4. System.Reflection.Moudle 提供了这些实例方法:GetType,GetTypes,FindTypes  
  
   设置反射类型的成员
   www.cnblogs.com/sosoft/
    反射类型的成员就是反射层次模型中最下面的一层数据。我们可以通过type对象的GetMembers 方法取得一个类型的成员。如果我们使用的是不带参数的GetMembers,它只返回该类型的公共定义的静态变量和实例成员,我们也可以通过使用带参数的GetMembers通过参数设置来返回指定的类型成员。具体参数参考msdn 中system.reflection.bindingflags 枚举类型的详细说明。
   
   例如:
  
   //设置需要返回的类型的成员内容
   
 

 bindingFlags bf=bingdingFlags.DeclaredOnly|bingdingFlags.Nonpublic|BingdingFlags.Public;  
   foreach (MemberInfo mi int t.getmembers(bf))    
   {    
    writeline(mi.membertype) //输出指定的类型成员    
   }

   通过反射创建类型的实例   

   通过反射可以获取程序集的类型,我们就可以根据获得的程序集类型来创建该类型新的实例,这也是前面提到的在运行时创建对象实现晚绑定的功能   
   我们可以通过下面的几个方法实现:  

   1. System.Activator 的CreateInstance方法。该方法返回新对象的引用。具体使用方法参见msnd   
   2. System.Activator 的createInstanceFrom 与上一个方法类似,不过需要指定类型及其程序集   
   3. System.Appdomain 的方法:createInstance,CreateInstanceAndUnwrap,CreateInstranceFrom和CreateInstraceFromAndUnwrap   
   4. System.type的InvokeMember实例方法:这个方法返回一个与传入参数相符的构造函数,并构造该类型。   
   5. System.reflection.constructinfo 的Invoke实例方法  
  
   反射类型的接口   

   如果你想要获得一个类型继承的所有接口集合,可以调用Type的FindInterfaces GetInterface或者GetInterfaces。所有这些方法只能返回该类型直接继承的接口,他们不会返回从一个接口继承下来的接口。要想返回接口的基础接口必须再次调用上述方法。   

   反射的性能:   

   使用反射来调用类型或者触发方法,或者访问一个字段或者属性时clr 需 要做更多的工作:校验参数,检查权限等等,所以速度是非常慢的。所以尽量不要使用反射进行编程,对于打算编写一个动态构造类型(晚绑定)的应用程序,可以采取以下的几种方式进行代替:   

1. クラス継承を通じて。コンパイル時に既知の基本型から型を派生させ、実行時にその型のインスタンスを作成し、その型への参照を基本型の変数に入れてから、基本型の仮想メソッドを呼び出します。

2. インターフェイスを通じて実装されます。実行時に、その型のインスタンスを構築し、そのインターフェイス型の変数にそのインスタンスへの参照を配置し、インターフェイスによって定義された仮想メソッドを呼び出します。

3.委任を通じて達成されました。名前とプロトタイプがコンパイル時に既知のデリゲートと一致するメソッドを型に実装させます。まず実行時に型のインスタンスを構築し、次にメソッドのオブジェクトと名前を使用してデリゲートのインスタンスを構築し、デリゲートを通じて必要なメソッドを呼び出します。前の 2 つの方法と比較して、この方法は作業量が多くなりますが、効率は低くなります。 。

以上がC#リフレクション技術コンセプトの機能とポイントの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。