C#式ツリーに関するアドバイス
-
03-07-2019 - |
質問
クラスのタイプ(またはインスタンス)とともに、パラメータとして式ツリーを受け入れるメソッドで作業しています。
基本的な考え方は、このメソッドが検証に使用されるコレクションに特定のものを追加するということです。
public interface ITestInterface
{
//Specify stuff here.
}
private static void DoSomething<T>(Expression<Func<T, object>> expression, params IMyInterface[] rule)
{
// Stuff is done here.
}
メソッドは次のように呼び出されます:
class TestClass
{
public int MyProperty { get; set; }
}
class OtherTestClass : ITestInterface
{
// Blah Blah Blah.
}
static void Main(string[] args)
{
DoSomething<TestClass>(t => t.MyProperty,
new OtherTestClass());
}
この方法を使用しているのは、渡されるプロパティ名を厳密に型指定したいからです。
私が苦労しているいくつかのこと..
- DoSomething内で、(渡された本体から)
PropertyInfo
タイプを取得し、rule []とともにコレクションに追加したい。現在、expression.Bodyを使用して&quot; Convert。([propertyname])&quot;から[propertyname]を削除することを考えています。リフレクションを使用して必要なものを取得します。これは面倒で間違っているようです。より良い方法はありますか? - これは私が使用している特定のパターンですか?
- 最後に、私がやっていることに対する私の誤解についての提案や説明があれば幸いです。また、C#式ツリーに関するリソースや良い情報もありがたいです。
ありがとう!
イアン
編集:
DoSomethingメソッド内で expression.Body.ToString()
が返す例は、&quot; Convert(t.MyProperty)&quot;を含む文字列です。上記の例から呼び出された場合。
厳密に入力する必要があるため、プロパティ名を変更してもコンパイルされません。
提案をありがとう!
解決
Expression.BodyからPropertyInfoオブジェクトを収集すると、別の質問に対する私の解決策。
他のヒント
現在のアプリケーションでやりたいことの多くをコンパイル時、つまり静的型チェックにプッシュするために、式ツリーに大きく依存しています。
式ツリーをトラバースして、「意味のある」何かに変換します。
私がやったことの1つは、URLの代わりに、ラムダ関数を宣言し、それを解釈するMVCのようなアプローチに依存していることです。コンパイラが生成した式ツリーをURLに変換します。このURLが呼び出されると、逆のことが行われます。このように、リンク切れのコンパイル時チェックと呼ばれるものがあり、これはリファクタリングやオーバーロードでもうまく機能します。このように式ツリーを使用することを考えるのはクールだと思います。
ビジターパターンをチェックアウトしたい場合があります。最初はあまり意味がありませんが、すべてを結び付けており、コンパイラ構築で型チェックを解決するための非常に正式な方法であるため、開始するのは苦痛です。同じこともできますが、型チェックの代わりに必要なものを出力します。
私が現在頭を痛めているのは、式の束を翻訳する(または実際に解釈する必要がある)ためのシンプルなフレームワークを構築し、JavaScriptを発行する機能です。コンパイラが生成した式ツリーは、オブジェクトモデルとのインターフェイスとなる有効なJavaScriptに変換されるという考え方です。
この点でエキサイティングなのは、間違ったときにコンパイラが常に教えてくれ、最終結果が単なる文字列の集まりであることを確認できる方法ですが、重要な部分はこれらの文字列の作成方法です。彼らはいくつかの検証を経て、それは何かを意味します。
一度そこに行くと、式ツリーではできないことはほとんどありません。
System.Reflection.Emitを使用している間、式ツリーを使用して動的コンパイル用の軽量フレームワークを作成していることがわかりました。コンパイル時に、動的に作成されたアセンブリもコンパイルできるかどうかが基本的にわかります。リフレクションと静的型チェックでシームレスに。これはさらに進んで、最終的に多くの時間を節約し、非常に機敏で堅牢であることが判明したものになりました。
だから私はこの種のものが大好きです。これがメタプログラミングのすべてであり、プログラムを実行するプログラムにプログラムを書くことです。これからも続けてください!
ここでこのプロパティを使用して何をしようとしているのか、感謝しています。私はこの難問にぶつかりました。書くのはいつも奇妙に感じる:
DoSomething("MyProperty", new OtherClass());
プロパティの名前が変更された場合、または呼び出しでテキストが誤って入力された場合、問題が発生します。私が学んだことは、これはおそらくテストを通して対処しなければならないことだということです。具体的には、単体テスト。 &Do; Something&quot;を強制するユニットテストを作成します。呼び出しは正しく機能します。
あなたが試みるかもしれないもう一つのことは、属性でプロパティを装飾し、属性を持つプロパティを探して構築されたときにクラスに反映し、ルールをロードすることです。
[DoSomething(typeof(OtherClass), typeof(OtherClass2))]
public int MyProperty
{
get;
set;
}
この場合、コンストラクターは(おそらく基本クラス内に?)動的にOtherClassオブジェクトとOtherClass2オブジェクトを作成し、それらをプロパティの名前と共にコレクションにロードします。