10

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

ただし、このようなコードは本当に「ごまかしている」と思わざるを得ません。つまり、提供された言語構造を使用して特定の目的を達成するのではなく、それらを回避することができます。

この種のコードはどの程度許容されますか? リスクは何ですか?このアプローチの正当な用途は何ですか?

4

6 に答える 6

8

リフレクションを使用するのはちょっと面倒な場合もありますが、多くの場合、リフレクションは最も優れたコード ツールです。

.Net プロパティ グリッドを見てください。Visual Studio を使用したことのある人なら誰でも知っているでしょう。任意のオブジェクトを指すことができ、単純なプロパティ エディターが生成されます。これはリフレクションを使用します。実際、VS のツールボックスのほとんどはリフレクションを使用します。

単体テストを見てください-それらはリフレクションによってロードされます(少なくともNUnitとMSTestでは)。

リフレクションにより、静的言語からの動的スタイルの動作が可能になります。

本当に必要なのはダック タイピングです。C# コンパイラは既にこれをサポートしています。インターフェイスを実装しているかどうかに関係なく、 のforeachようなものなら何でもかまいません。IEnumerableというメソッドを持つ任意のクラスで C#3 コレクション構文を使用できますAdd

動的なスタイルの動作が必要な場合はいつでもリフレクションを使用してください。たとえば、オブジェクトのコレクションがあり、それぞれで同じプロパティをチェックしたい場合などです。

リスクは動的型の場合と同様です。コンパイル時の例外が実行時の例外になります。コードは「安全」ではなく、それに応じて対応する必要があります。

.Net リフレクション コードは非常に高速ですが、明示的な呼び出しほど高速ではありません。

于 2008-09-07T09:59:16.023 に答える
3

私は同意します、それは私にそれが機能することを私に与えますが、それはハック 感のように感じます. 私は可能な限り反射を避けるようにしています。反映されたコードをリファクタリングした後、私は何度もやけどを負いました。コードは正常にコンパイルされ、テストも実行されますが、特別な状況 (テストではカバーされていません) では、リフレクション コードが突っ込んだオブジェクトの 1 つでリファクタリングを行ったため、プログラムは実行時に爆発します。

例 1: OR マッパーでのリフレクション。オブジェクト モデル内のプロパティの名前または型を変更すると、実行時間が大幅に短縮されます。

例 2:あなたは SOA ショップにいます。Web サービスは完全に分離されています (または、そう思われます)。これらには、生成されたプロキシ クラスの独自のセットがありますが、マッピングで時間を節約することにし、次のようにします。

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

内部ではこれもリフレクションですが、.net フレームワーク自体によって行われます。InternalColor.Greyの名前をInternalColor.Grayに変更するとどうなるでしょうか。すべてが問題ないように見え、問題なくビルドされ、問題なく実行されます..愚かなユーザーが灰色の色を使用することを決定する日まで.その時点でマッパーは爆発します.

于 2008-09-07T09:37:01.597 に答える
2

リフレクションは、私にとってなくてはならない素晴らしいツールです。これにより、プログラミングがはるかに簡単かつ高速になります。

たとえば、ORM レイヤーでリフレクションを使用して、テーブルの列値をプロパティに割り当てることができます。リフレクションがなければ、テーブル/クラス マッピングごとにコピー クラスを作成する必要がありました。

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

同じ問題が、.Net のすべての高度なプログラミングに当てはまります。「大いなる力には大いなる責任が伴う」。リフレクションを使用すると、大きな力が得られます。ただし、正しく使用する方法を知っていることを確認してください。ウェブ上には数十の例があります。

于 2009-03-30T19:03:34.407 に答える
1

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

たとえば、生成されたクラスは次のようになります。

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

どちらかのクラスにプロパティがないか、タイプが変更されている場合、コードはコンパイルされません。さらに、時代には大きな改善があります。

于 2008-09-07T07:38:40.617 に答える
1

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

于 2008-09-07T10:01:54.457 に答える
0

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

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

于 2012-04-17T17:39:25.377 に答える