【发布时间】:2011-01-07 17:13:54
【问题描述】:
我正在尝试编写一个简单的生成器,它使用表达式树来动态生成一个方法,该方法将一个类型实例的所有属性与该类型的另一个实例的属性进行比较。这适用于大多数属性,例如 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。那么为什么我不能将DateTime? 传递给它,因为它可以转换为object?如果我查看Nullable<T>,它确实覆盖了Equals(object o)。
PS:我意识到这还不是一个合适的生成器,因为它无法处理 null 值,但我会解决的 :)
更新:Iraklis 的回答确实解决了这个特殊问题,但最后我选择了一种我认为就足够了的更简单的方法:只需使用Expression.Equal。我认为这涵盖了我 99% 的案例(不确定它是否可以在不覆盖 == 的情况下处理覆盖 Equals,但没关系)。
【问题讨论】:
标签: c# .net expression-trees dynamic-method