2008-09-06 10 views
10

C#コードでのリフレクションの妥当性について疑問を持っています。たとえば、指定されたソースオブジェクトのプロパティを繰り返し処理し、指定された型の新しいインスタンスを作成し、同じ名前のプロパティの値を別のものにコピーする関数を作成しました。私はLINQの複数のテーブルからの継承の欠如を回避するために、ある自動生成LINQオブジェクトから別のLINQオブジェクトにデータをコピーするためにこれを作成しました。C#でのリフレクションの正当性

しかし、このようなコードは実際には「不正」であると考えられます。つまり、提供された言語構造を使用して特定の目的を達成するのではなく、回避することができます。

この程度のコードは受け入れられますか?リスクは何ですか?このアプローチの正当な利用は何ですか?

答えて

1

これは私だけかもしれませんが、私がこれに入る方法は、コードジェネレータを作成することです - 実行時のリフレクションを使用するのは少しコストがかかり、型なしです。最新のコードに従って生成され、強力に型付けされた方法ですべてをコピーするクラスを作成すると、ビルド時にこれらのエラーをキャッチすることになります。

例えば、生成されたクラスは、次のようになります。いずれかのクラスは、プロパティを持っていないか、またはそれらの型が変更さ

static class AtoBCopier 
{ 
    public static B Copy(A item) 
    { 
     return new B() { Prop1 = item.Prop1, Prop2 = item.Prop2 }; 
    } 
} 

場合、コードはコンパイルされません。さらに、時間の大幅な改善があります。

2

私は同意します、それは私にを与えますが、それはハックのように感じる感じ。私は可能な限り反射を避けようとしています。私はそれに反映されたコードをリファクタリングした後、何度も焼かれました。コードはうまくコンパイルされ、テストも実行されますが、特殊な状況(テストではカバーしていない)では、リフレクションコードが突き刺されたオブジェクトのリファクタリングによってプログラムが実行時間を浪費します。

例1: ORマッパーでのリフレクションでは、オブジェクトモデル内のプロパティの名前またはタイプを変更します。ランタイムを吹き飛ばします。

例2:あなたはSOAショップにいます。 Webサービスは完全に分離されています(つまり、あなたは思っています)。彼らは、生成されたプロキシクラスの独自のセットを持っている、しかし、あなたはいくつかの時間を節約することを決定し、あなたがこれを行うマッピングで:カバーの下に

ExternalColor c = (ExternalColor)Enum.Parse(typeof(ExternalColor), 
              internalColor.ToString()); 

これも反映しているが、.NET Frameworkの自体によって行わ。名前を変更するとどうなりますかInternalColor.GreyInternalColor.Gray?すべてが大丈夫だ、それは上手くビルドされ、さらにはうまくいく..愚かなユーザーが色を使用することを決定する日までグレー...どの時点でマッパーが爆破するか。

8

時には反射を使用するとハックのビットになることがありますが、多くの場合、これは単に最も優れたコードツールです。

.NETプロパティグリッドを参照してください.Visual Studioを使用している人は誰でもそれに精通しています。任意のオブジェクトを指すことができ、単純なプロパティエディタを生成します。実際にはVSのツールボックスのほとんどが反射を使用しています。

ユニットテストは、(少なくともNUnitとMSTestでは)リフレクションによって読み込まれています。

Reflectionでは、静的言語の動的スタイルの動作が可能です。

ダックタイピングは、C#コンパイラがすでにサポートしています。foreachは、インターフェイスを実装するかどうかにかかわらず、IEnumerableのように見えます。 Addというメソッドを持つどのクラスでも、C#3コレクション構文を使用できます。

ダイナミックスタイルの動作が必要な場合はどこでもリフレクションを使用します。たとえば、オブジェクトのコレクションがあり、それぞれのプロパティを同じにする場合などです。

ダイナミック型のリスクは同様です。コンパイル時の例外は実行時の例外になります。コードは「安全」ではないので、それに応じて対応する必要があります。

.Net反射コードは非常に速いですが、明示的な呼び出しが行われていたほど速くはありません。

+0

プロの意見と反対意見が尋ねられたら、これは適切な答えでしょうか? –

1

最近、特定のインターフェイスの実装を見つけるためにC#でリフレクションを使用しました。私はクラス名に基づいて計算の各ステップの "アクション"を調べる単純なバッチスタイルのインタプリタを書いていました。現在のネームスペースを反映させると、Execute()できるIStepインタフェースの正しい実装がポップアップします。このように、新しい「アクション」を追加することは、新しい派生クラスを作成するのと同じくらい簡単です。レジストリに追加する必要はありません。レジストリに追加する必要はありません。

2

リフレクションは素晴らしいツールです私はそれなしでは生きられなかった。それはプログラミングをはるかに容易かつ迅速にすることができます。

たとえば、ORMレイヤーでリフレクションを使用して、テーブルのカラム値を持つプロパティを割り当てることができます。それが反映されていない場合は、各テーブル/クラスマッピングのコピークラスを作成しなければなりませんでした。

上記の外色の例外については、問題はEnum.Parseではなく、コーダーが適切な例外をキャッチしなかったことです。文字列が解析されるので、コーダは、文字列に間違った値が含まれていると常に想定する必要があります。

同じ問題は、.Netのすべての高度なプログラミングに適用されます。 「大きな力をもって、大きな責任を負う」反射を使用することで多くのパワーが得られます。しかし、あなたがそれを適切に使用する方法を知っていることを確認してください。ウェブには数多くの例があります。

0

リフレクションでは、プラグインDLLが実行時に自動的にロードされる(コンパイル時に明示的にリンクされていない)プラグインアーキテクチャを実装するのが非常に簡単になります。

これらは、関連するインタフェース/クラスを実装/拡張するクラスについてスキャンすることができます。リフレクションを使用して、オンデマンドでこれらのインスタンスをインスタンス化できます。

関連する問題