式ツリーを使用して、あるタイプのインスタンスのすべてのプロパティをそのタイプの別のインスタンスのプロパティと比較するメソッドを動的に生成する単純なジェネレーターを作成しようとしています。int
これは、などのほとんどのプロパティで正常に機能しますが、 (およびおそらく他のnull許容値タイプ)string
では失敗します。DateTime?
方法:
static Delegate GenerateComparer(Type type)
{
var left = Expression.Parameter(type, "left");
var right = Expression.Parameter(type, "right");
Expression result = null;
foreach (var p in type.GetProperties())
{
var leftProperty = Expression.Property(left, p.Name);
var rightProperty = Expression.Property(right, p.Name);
var equals = p.PropertyType.GetMethod("Equals", new[] { p.PropertyType });
var callEqualsOnLeft = Expression.Call(leftProperty, equals, rightProperty);
result = result != null ? (Expression)Expression.And(result, callEqualsOnLeft) : (Expression)callEqualsOnLeft;
}
var method = Expression.Lambda(result, left, right).Compile();
return method;
}
DateTime?
プロパティでは、次のように失敗します。
タイプ'System.Nullable`1[System.DateTime]'の式は、メソッド'Boolean Equals(System.Object)'のタイプ'System.Object'のパラメーターには使用できません。
Equals
OK、それでそれはそれが期待する過負荷を見つけobject
ます。それで、DateTime?
それがに変換可能であるので、なぜ私はそれに渡すことができないのobject
ですか?私が見るとNullable<T>
、それは確かにのオーバーライドを持っていますEquals(object o)
。
PS:値を処理できないため、これはまだ適切なジェネレーターではないことに気付きましたが、それnull
については説明します:)
更新:Iraklisの答えはこの特定の問題に対しては機能しましたが、最終的には、私が十分だと思うはるかに単純なアプローチを採用しました。単にを使用してExpression.Equal
ください。私の場合の99%をカバーしていると思います(オーバーライドEquals
せずにオーバーライドを処理できるかどうかはわかりませんが、問題ありません==
)。