1. ホーム
  2. cp

C#の構文]をご覧ください。C#のリフレクション(アセンブリ)機構を説明する

2022-02-20 06:54:51

はじめに

        リフレクションは、C#の特徴的な技術の1つです。これにより、プログラミングをより柔軟に行うことができるようになり、多少の性能低下はあるものの、クラスやメソッド名で簡単にクラスを構築したり、メソッドを呼び出したりすることができるようになりました。
リフレクションの定義を見てみましょう。
        Reflectionの定義:メタデータを調べてその型情報を収集する機能、メタデータ(編集された基本データ単位)はテーブルの束、コンパイラはクラス定義テーブル、フィールド定義テーブル、メソッド定義テーブルなどを作成し、System.Reflection名前空間はこのメタデータからコードを反映(パース)できるいくつかのクラスが含まれています。
        Reflection名前空間には、これらのメタデータにコードを反映(パース)させるためのクラスがいくつか含まれています。クラス名の文字列を使ってこのクラスを作成すると、プログラムは保存されたクラスのテーブルから指定したクラス名を探し出し、対応するコンストラクタを見つけて実行します。

II. 反射のタイプ

メンバー情報 -反映されたクラスのメンバ
コンストラクタ情報 -リフレクションクラスのコンストラクタ
フィールドインフォ リフレクションクラスのフィールド
メソッドインフォ クラスのコンストラクタのメソッドを反映します。
プロパティ情報 -反映されたクラスのコンストラクタのプロパティ
イベント情報 -Reflectionクラスのコンストラクタのイベント

III. 反射関連操作

3.1 テスト環境の準備

        導入したいダイナミックリンクライブラリとしてC#のクラスライブラリTestDllを新規に作成し、メインアプリケーションとしてWinformプロジェクトRefDllを新規に作成します。



        クラスライブラリには、リフレクションを導入する必要があるクラスとして、以下のクラスを追加します。

public class Test { }

3.2 データセットを反射として生成するためのDLLをロードする

        アセンブリオブジェクトのLoadFromメソッドでdllをロードし、データセットオブジェクトのインスタンスを生成します。
string plugin = "TestDll.dll";
Assembly assembly = Assembly.LoadFrom(plugin);

        生成されたアセンブリは、我々が必要とするデータセットオブジェクトであり、我々はこのオブジェクトの上に実施する反射機構に関連するすべてのその後の操作は、アセンブリのLoad()、LoadFile()データセット情報を生成するには、他の二つのメソッドがありますが、違いはここで詳しく説明されていない、GoogleやBaidu独自の上です。

3.3 データセットに含まれるすべてのデータタイプを取得する (つまり、DLLで定義したクラスを取得する)

Type[] types = assembly.GetTypes();
Type type= types[0];



        dllではクラスを1つしか定義していないため、ここでの型は要素が1つだけになりますが、これは実際のプログラミングでは探索のためのループが必要になることが多いので、その後のコードで説明しやすいように抽出したものです。

3.4 クラスオブジェクトのインスタンスを構築する

        ここで、Test クラスに 2 つのコンストラクタを追加します。1 つはパラメータ付き、もう 1 つはパラメータ無しで、Test オブジェクトを 2 種類の形式で作成します。
public class Test
{
private int m_i = 0;
public Test()
{

}
private Test(int i)
{
m_i = i;
}


}



        参照不要の構成体を呼び出す。
object obj1 = assembly.CreateInstance(type.FullName);

        あるいは
object obj1 = Activator.CreateInstance(type);



        パラメータを指定してコンストラクタを呼び出す。
object[] objs=new object[1];
objs[0]=1;
object obj2 = assembly.CreateInstance(type.FullName, false, BindingFlags.CreateInstance, null, objs, null, null);



        あるいは
   object obj2 = Activator.CreateInstance(type, objs);




        オブジェクトのインスタンスを生成するために、アセンブリまたはアクティベータのCreateInstanceメソッドを使用しました。参照コンストラクタの呼び出しでは、オーバーロード版のCreateInstanceはいくつかのパラメータを使用します。2番目のパラメータは、クラス名を検索するときに大文字小文字を無視するかどうかを参照し、ここではfalseは無視しないことを意味します。3番目のパラメータは検索フラグのビットで、ここではクラスインスタンスを作成したいので、BindingFlags.CreateInstanceを使用するか、BindingFlags.CreateInstanceを使用します。5番目のパラメータは、もちろん、コンストラクタに渡すパラメータのリストです。CreateInstanceの詳しい使い方は、MSDNを参照してください。

3.5 クラス内のメソッドを呼び出す

        ここで、Test クラスにテスト用のメソッドを追加します。
public void fun1()
{
MessageBox.Show("func1");
}



        このメソッドを呼び出すためにリフレクションを使用します。まず、クラスのすべてのメソッドのリストを取得します。
MethodInfo[] minfos = type.GetMethods();



        MethodInfoは、クラス内のメソッドに関する情報です。それを辿って必要なメソッドのMethodInfoを見つけ、Invoke of MethodInfoやInvokeMember of Typeを使ってメソッドをトリガーする。
foreach (MethodInfo me in minfos)
{
if (me.Name == "func1")
{
me.Invoke(obj1, null);
type.InvokeMember(me.Name,BindingFlags.InvokeMethod,null,obj1,null);

}
}



        MethodInfo.Invokeは2つのパラメータを受け取ります。1つ目は作成したクラスオブジェクトのインスタンス、2つ目は呼び出されたメソッドから渡されるパラメータのリスト、object[] 型、func1 のパラメータは null なので、ここでは null が渡されます。 型 .InvokeMember 有効パラメータと MethodInfo.Invokeは、object[] 型のパラメータを受け取り、object[] 型のパラメータを受け取ります。InvokeMemberは、追加のオーバーライドフラグBindingFlags.InvokeMethodを持つことを除いて、MethodInfo.Invokeと似ています。

3.6 クラスの全フィールドの取得

        まず、Testクラスのm_iメンバープロパティをpublicに変更することから始めます。
public int m_i = 0;



        そして、以下のコードでm_iフィールドを取得することができます。
FieldInfo[] finfo = type.GetFields();



3.7 クラスの全イベントの取得

        Test クラスに以下のカスタムイベントを追加します。
// Define delegate
public delegate void BtnClickHandle(object sender, EventArgs e);
//define event
public event BtnClickHandle UserControlBtnClicked;



        このイベントの定義を取得します。
EventInfo[] einfo = type.GetEvents();



3.8 コンストラクタの取得

ConstructorInfo[] cinfo = type.GetConstructors();



3.9 全メンバーを取得する

MemberInfo[] memInfo = type.GetMembers();



Githubの場所。
https://github.com/HymanLiuTS/CSGroup
このアイテムのクローンを作成します。
git clone [email protected]:HymanLiuTS/ CSGroup.git
この記事のソースコードを取得する
git checkout CSL01