c#反射


アウトライン:
1、反射とは何か
2、ネーミングスペースと組立品の関係
3、運行期間がタイプ情報を得るのに何の役に立つか
4、反射取得タイプの使用方法
5、タイプに応じてオブジェクトを動的に作成する方法
6、メソッドの取得方法および動的呼び出し方法
7、動的作成依頼
1、反射とは何か
Reflection、中国語を反射に訳します.
これはNetでランタイムタイプ情報を取得する方法、Netのアプリケーションは、「プログラムセット(Assembly)」、「モジュール(Module)」、「タイプ(class)」のいくつかの部分から構成され、反射は、プログラマがプログラムの実行期間中にこれらの部分に関する情報を取得できるようにするプログラムを提供します.たとえば、次のようにします.
Assemblyクラスでは、実行中の組立品情報を取得したり、動的に組立品をロードしたり、組立品でタイプ情報を検索したりして、そのタイプのインスタンスを作成できます.
Typeクラスは、オブジェクトのすべての要素、メソッド、コンストラクタ、プロパティなどを含むオブジェクトのタイプ情報を取得し、Typeクラスによってこれらの要素の情報を取得して呼び出すことができます.
MethodInfoにはメソッドの情報が含まれており,このクラスでメソッドの名前,パラメータ,戻り値などを得ることができ,呼び出すことができる.
など、FieldInfo、EventInfoなど、これらのクラスはSystemに含まれています.Reflectionネーミングスペースの下.
2、ネーミングスペースと組立品の関係
多くの人はこの概念に対してまだはっきりしていないかもしれませんが、合格した人に対しては.Netプログラマーは、この点を明らかにする必要があります.
ネーミングスペースはJavaのパッケージと似ていますが、Javaのパッケージはディレクトリ構造に従って配置する必要があり、ネーミングスペースは必要ありません.
組立品は.Netアプリケーションが実行する最小単位、コンパイルされた.dll、.exeはすべて組立品です.
組立品とネーミングスペースの関係は1つの対応ではなく、互いに含まれていない.1つの組立品には複数のネーミングスペースがあり、1つのネーミングスペースも複数の組立品に存在することができる.このように言うと、少しぼやけているかもしれない.例を挙げると、

   A:
namespace   N1
{
      public   class   AC1   {…}
      public   class   AC2   {…}
}
namespace   N2
{
      public   class   AC3   {…}
      public   class   AC4{…}
}
   B:
namespace   N1
{
      public   class   BC1   {…}
      public   class   BC2   {…}
}
namespace   N2
{
      public   class   BC3   {…}
      public   class   BC4{…}
}

この2つの組立品にはN 1とN 2の2つのネーミングスペースがあり、それぞれ2つのクラスが宣言されています.これは完全に可能です.次に、1つのアプリケーションで組立品Aを参照します.では、このアプリケーションでは、N 1の下のクラスはAC 1とAC 2であり、N 2の下のクラスはAC 3とAC 4であることがわかります.
次にAへの参照を抜き、Bへの参照を加えると、このアプリケーションで見られるN 1の下のクラスはBC 1とBC 2、N 2の下にも同じになります.
この2つの組立品を同時に参照すると、N 1の下には、AC 1、AC 2、BC 1、BC 2の4つのクラスが表示されます.
       
ここまで、私たちは1つの概念を理解することができて、ネーミング空間はただ1つのタイプがその族であることを説明して、例えばある人は漢族で、ある人は回族です;アクセサリーは、北京に住んでいる人や上海に住んでいる人など、タイプがどこに住んでいるかを示しています.では、北京には漢族人もいれば、回族人もいます.上海には漢族人もいれば、回族人もいます.これは矛盾しません.前述したように、アセンブリはタイプが住んでいる場所です.では、プログラムでクラスを使用するには、コンパイラというクラスがどこに住んでいるかを教えなければなりません.コンパイラはそれを見つけることができます.つまり、アセンブリを参照する必要があります.では、プログラムを書くときに、このクラスがどこにあるか分からないかもしれませんが、名前だけを知っていると、使えないのでしょうか.答えはいいです.これは反射です.プログラムが実行されている間にこのタイプのアドレスを提供して、それを見つけます.
興味があれば、続けて下を見ましょう.
3、運行期間がタイプ情報を得るのに何の役に立つか
開発時にコードを書くことができる以上、なぜ実行期間に置くのか、煩雑であるだけでなく、効率にも影響を与えるのではないかと疑問に思う人もいるかもしれません.
これは仁見智の問題で、早バインドと晩バインドと同じように、異なる場合に適用されます.遅いバインドに反対する人もいますが、効率を損なう理由がありますが、多くの人が虚関数のメリットを享受している間に、彼が遅いバインドを使っていることに気づいていません.この問題ははっきり言って、二言三言ではっきり言えるものではないので、ここまで注文しました.
私の見方は、晩バインドは多くの設計上の便利さをもたらすことができて、適切な使用はプログラムの多重性と柔軟性を大いに高めることができて、しかしいかなるものにも両面性があって、使う時、再三測定する必要があります.
次に、運転期間でタイプ情報を得るのはいったい何の役に立つのでしょうか.
やはり例を挙げて説明します.多くのソフトウェア開発者は自分のソフトウェアにインタフェースを残すのが好きです.他の人はプラグインを書いてソフトウェアの機能を拡張することができます.例えば、私はメディアプレーヤーを持っています.後で識別のフォーマットを簡単に拡張したいと思っています.では、インタフェースを宣言します.

public   interface   IMediaFormat
{
    string   Extension   {get;}
    Decoder   GetDecoder();
}

このインタフェースにはExtensionプロパティが含まれています.このプロパティはサポートされている拡張子を返し、もう一つのメソッドはデコーダのオブジェクトを返します(ここではDecoderのクラスを仮定します.このクラスはファイルストリームを復号する機能を提供し、拡張プラグインは派生することができます).デコーダオブジェクトを通じてファイルストリームを説明することができます.
では、すべての復号プラグインがデコーダを派生させ、このインタフェースを実現し、GetDecoderメソッドでデコーダオブジェクトを返し、そのタイプの名前を私のプロファイルに構成する必要があります.
これにより、プレーヤーを開発する際に将来拡張されるフォーマットのタイプを知る必要はなく、プロファイルから現在のすべてのデコーダのタイプ名を取得し、メディアフォーマットを動的に作成するオブジェクトをIMediaFormatインタフェースに変換して使用する必要があります.
これが反射の典型的な応用である.
4、反射取得タイプの使用方法
まず、タイプ情報をどのように取得するかを見てみましょう.
タイプ情報を取得するには、インスタンスオブジェクトを取得する2つの方法があります.
この場合、私はこのインスタンスオブジェクトを得るだけで、objectの参照かもしれないし、インタフェースの参照かもしれないが、私はその正確なタイプを知らないので、システムを呼び出すことができます.Objectに宣言されたメソッドGetTypeは、インスタンスオブジェクトのタイプオブジェクトを取得します.たとえば、メソッド内で、渡されたパラメータがインタフェースを実装したかどうかを判断する必要があります.実装された場合、インタフェースのメソッドを呼び出します.

…
public   void   Process(   object   processObj   )
{
    Type   t   =   processsObj.GetType();
    if(   t.GetInterface(“ITest”)   !=null   )
                    …
}
…

別の取得方法はType.GetTypeおよびAssembly.GetTypeメソッド:
              Type   t   =   Type.GetType(“System.String”);
前述したネーミングスペースとアセンブリの関係について説明したが、クラスを検索するには、そのアセンブリを指定するか、取得したAssemblyインスタンスの上でGetTypeを呼び出す必要があります.
この組立品のタイプはタイプ名のみを書き込むことができ、もう一つの例外はmscorlibです.dll、この組立品に宣言されているタイプは、組立品名を省略することもできます(.Net組立品のコンパイル時には、コンパイル時に参照しないことを明確に指定しない限り、デフォルトではmscorlib.dllが参照されます).

     System.String  mscorlib.dll    ,   Type   t   =   Type.GetType(“System.String”)    
     System.Data.DataTable  System.Data.dll    ,  :
Type.GetType(“System.Data.DataTable”)        。
  :Type   t   =   Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0,   Culture=neutral,   PublicKeyToken=b77a5c561934e089");
 

これでいいです.次の投稿を見てください.
http://expert.csdn.net/Expert/topic/2210/2210762.xml?temp=.1919977
qqqchenの答えはすばらしかった
5、タイプに応じてオブジェクトを動的に作成する方法
    System.Activatvatorは、タイプに応じてオブジェクトを動的に作成する方法を提供します.たとえば、DataTableを作成します.

        Type   t   =   Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0,   Culture=neutral,   PublicKeyToken=b77a5c561934e089");
        DataTable   table   =   (DataTable)Activator.CreateInstance(t);


例2:パラメータ付きコンストラクタに基づいてオブジェクトを作成する

namespace   TestSpace   {
    public   class   TestClass
    {
          private   string   _value;
          public   TestClass(string   value)   {
                _value=value;
      }
    }
}
…
Type   t   =   Type.GetType(“TestSpace.TestClass”);
Object[]   constructParms   =   new   object[]   {“hello”};   //     
TestClass   obj   =   (TestClass)Activator.CreateInstance(t,constructParms);
…
           Object     


6、メソッドの取得方法および動的呼び出し方法

namespace   TestSpace
{
      public   class   TestClass   {
          private   string   _value;
          public   TestClass()   { }
          public   TestClass(string   value)   {
                _value   =   value;
          }
          public   string   GetValue(   string   prefix   )   {
                if(   _value==null   )
                    return   "NULL";
                else
                  return   prefix+"   :   "+_value;
          }
            public   string   Value   {
                set   {
                    _value=value;
                }
                get   {
                    if(   _value==null   )
                            return   "NULL";
                    else
                            return   _value;
                }
            }
      }
}

上は単純なクラスで、パラメータのあるコンストラクタ、GetValueのメソッド、Valueのプロパティが含まれています.メソッドの名前でメソッドを取得し、呼び出すことができます.たとえば、次のようにします.

//      
Type   t   =   Type.GetType("TestSpace.TestClass");
//      
object[]   constuctParms   =   new   object[]{"timmy"};
//        
object   dObj   =   Activator.CreateInstance(t,constuctParms);
//       
MethodInfo   method   =   t.GetMethod("GetValue");
//          ,      Public       ,       
BindingFlags   flag   =   BindingFlags.Public   |   BindingFlags.Instance;
//GetValue     
object[]   parameters   =   new   object[]{"Hello"};
//    ,   object     
object   returnValue   =   method.Invoke(dObj,flag,Type.DefaultBinder,parameters,null);
            ,       MSDN

7、動的作成依頼
依頼はC#でイベントを実現するための基礎であり、動的に依頼を作成することは避けられない場合があるが、実際に依頼も一種のタイプであるSystem.Delegate、すべての依頼はこのクラスから派生しています.
    System.Delegateは、委任などの委任を動的に作成するための静的方法を提供します.

namespace   TestSpace   {
      delegate   string   TestDelegate(string   value);
      public   class   TestClass   {
            public   TestClass()   { }
            public   void   GetValue(string   value)   {
                    return   value;
            }
        }
}
    :
TestClass   obj   =   new   TestClass();

//    ,           typeof     
Type   t   =   Type.GetType(“TestSpace.TestClass”);
//    ,    、             
TestDelegate   method   =   (TestDelegate)Delegate.CreateDelegate(t,obj,”GetValue”);
String   returnValue   =   method(“hello”);


ここまで、反射の役割と基本的な使い方を簡単に説明しましたが、まだ多くの面で触れていません.興味のある方はMSDNを参考にすることができます.
不思議なことに、多くの人はMSDNを見たくありません.実はあなたが望んでいる答えは、99%が中で見つけることができます.