ほとんどの高レベルの動的型言語は反射的であると言われています。ウィキペディアのリフレクション(コンピュータープログラミング)は説明していますが、それが何を意味するのかを明確に示しているわけではありません。誰かが関連する例によってそれをより簡単な方法で説明できますか?
5 に答える
リフレクションを実際的な方法で使用する方法の例を示すには、次のようにします。
プラグインを使用して拡張したいアプリケーションを開発していると仮定しましょう。これらのプラグインは、Personという名前のクラスのみを含む単純なアセンブリです。
namespace MyObjects
{
public class Person
{
public Person() { ... Logic setting pre and postname ... }
private string _prename;
private string _postname;
public string GetName() { ... concat variabes and return ... }
}
}
プラグインは実行時にアプリケーションを拡張する必要があります。つまり、アプリケーションがすでに実行されている場合は、コンテンツとロジックを別のアセンブリからロードする必要があります。これは、これらのリソースがアセンブリ、つまりMyApplication.exeにコンパイルされていないことを意味します。それらがライブラリMyObjects.Person.dllにあると仮定しましょう。
これで、この情報を抽出し、たとえばMyObjects.PersonからGetName()関数にアクセスする必要があるという事実に直面します。
// Create an assembly object to load our classes
Assembly testAssembly = Assembly.LoadFile(Application.StartUpPath + @"MyObjects.Person.dll");
Type objType = testAssembly.GetType("MyObjects.Person");
// Create an instace of MyObjects.Person
var instance = Activator.CreateInstance(objType);
// Call the method
string fullname = (string)calcType.InvokeMember("GetName",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public,
null, instance, null);
ご覧のとおり、ランタイムでのリソースの動的ロードにSystem.Reflectionを使用できます。これは、使用方法を理解するのに役立つ場合があります。
アセンブリにアクセスする方法の例については、このページをご覧ください。基本的に私が書いたものと同じ内容です。
リフレクションをよりよく理解するために、プログラムを評価するインタプリタを考えてみてください。インタプリタは、他のプログラムを評価するプログラムです。
プログラムは、(1)検査し、(2)自身の状態/動作、またはプログラムを実行しているインターパーターの状態/動作を変更することができます(b)。
その場合、4つの組み合わせがあります。各種類のアクションの例を次に示します。
- 1a-オブジェクトが持つフィールドのリストを読み取ります
- 2a-フィールドの名前に基づいて1つのフィールドの値を変更します。メソッドのリフレクティブ呼び出し。
- 1b-現在のスタックを調べて、実行されている現在のメソッドを確認します
- 2b-スタックまたは言語での特定の操作の実行方法(メッセージ送信など)を変更します。
タイプaは構造反射と呼ばれます。タイプbは行動反射と呼ばれます。タイプaの反映は、言語でかなり簡単に実現できます。タイプbの反映は、特に2bの方がはるかに複雑です。これは、オープンリサーチのトピックです。ほとんどの人が振り返って理解するのは1aと2aです。
リフレクションを理解するには、具体化の概念を理解することが重要です。インタプリタが解釈されるプログラム内のステートメントが評価されるとき、インタプリタはそれを表す必要があります。インタプリタには、おそらく、解釈されるプログラムのフィールドやメソッドなどをモデル化するためのオブジェクトがあります。結局のところ、インタプリタもプログラムです。リフレクションを使用すると、インタプリタされたプログラムは、それ自体の構造を表すインタプリタ内のオブジェクトへの参照を取得できます。これが具体化です。(次のステップは、因果関係を理解することです)
反射機能にはさまざまな種類があり、反射するものとそうでないもの、およびそれが何を意味するのかを理解するのが難しい場合があります。プログラムと通訳の観点から考える。ウィキペディアのページ(改善される可能性があります)を理解するのに役立つことを願っています。
リフレクションは、実行時に作成したプログラムのメタデータをクエリする機能です。たとえば、アセンブリ内で検出されるクラス、それらのクラスに含まれるメソッド、フィールド、プロパティなどです。
.netには「属性」も含まれています。これらはクラス、メソッド、フィールドなどで装飾できるクラスです。これらの目的はすべて、実行時にクエリできるカスタマイズされたメタデータを追加することです。
多くの場合、詳細はメタデータのみに依存します。検証時には、stringやintは気にしませんが、nullであってはならないことに気を配っています。したがって、その場合、特定のクラスを気にせずにチェックするプロパティまたは属性が必要です。そこに反射が現れます。また、メソッドをオンザフライで生成する場合(C#4.0の動的オブジェクトで使用可能)と同じように、リフレクションを使用することもできます。基本的には、ビヘイビア駆動またはアスペクト指向プログラミングを行うのに役立ちます。
もう1つの一般的な使用法は、テストフレームワークです。彼らはリフレクションを使用して、プロキシ環境でテストおよび実行するメソッドを見つけます。
これは、実行時情報に基づいて動作を適応させるプログラミング言語の機能です。.Net / C#の世界では、これは頻繁に使用されます。たとえば、データをxmlにシリアル化する場合、属性を追加して、結果のxmlのフィールドの名前を指定できます。
これはおそらくprogrammers.stackexchange.comにとってより良い質問です。
ただし、基本的には、コード内からコードを確認できることを意味します。
私のVB6の時代には、Textプロパティを持つUIオブジェクトと、Description(またはとにかく「Text」以外のもの)を持つUIオブジェクトがありました。両方の種類のオブジェクトを同じように処理するコードをカプセル化できなかったため、これは苦痛でした。リフレクションを使用すると、少なくとも、オブジェクトにTextプロパティまたはDescriptionプロパティがあるかどうかを確認できたはずです。
または、オブジェクトの両方にTextプロパティがある場合もありますが、それらは異なる基本クラスから派生し、インターフェイスが適用されていません。繰り返しますが、リフレクションの助けなしに静的に型付けされた言語でこのようなコードをカプセル化することは困難ですが、リフレクションを使用すると、静的に型付けされた言語でもそれを処理できます。