我正在嘗試編寫一個簡單的生成器,它使用表達式樹來動態生成一個方法,將某個類型的實例的所有屬性與該類型的另一個實例的屬性進行比較。這適用於大多數屬性,如int
和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的]' 不能被用於類型的參數「System.Object的」的方法「布爾等於(System.Object的)」
行,所以它發現期望的Equals
過載。那麼爲什麼我不能通過DateTime?
進去呢,因爲它可以兌換成object
?如果我看看Nullable<T>
,它的確可以覆蓋Equals(object o)
。
PS:我知道這是不是一個合適的發電機又因爲它不能與null
值處理,但我會到達那個:)
UPDATE:伊拿克里斯的回答做了爲這個特定的問題工作,但最後我去了一個更簡單的方法,我認爲就足夠了:只需使用Expression.Equal
即可。我認爲這涵蓋了99%的案例(不知道它是否可以處理覆蓋Equals
而不是覆蓋==
,但沒關係)。
謝謝,該方法解決了我的問題,但最終我完全採用了不同的方法。 – stringargs 2011-01-10 10:11:48