我正在尝试编写一个简单的生成器,它使用表达式树来动态生成一个方法,该方法将一个类型实例的所有属性与该类型的另一个实例的属性进行比较。这适用于大多数属性,例如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]' 类型的表达式不能用于方法 'Boolean Equals(System.Object)' 的 'System.Object' 类型的参数
好的,所以它发现了Equals
期望的重载object
。那么为什么我不能将 a 传递给DateTime?
它,因为它可以转换为object
?如果我看一下Nullable<T>
,它确实有Equals(object o)
.
PS:我意识到这还不是一个合适的生成器,因为它不能处理null
值,但我会解决的:)
更新:Iraklis 的回答确实适用于这个特定问题,但最后我采用了一种我认为就足够了的更简单的方法:只需使用Expression.Equal
. 我认为这涵盖了我 99% 的情况(不确定它是否可以在Equals
不覆盖的情况下处理覆盖==
,但没关系)。