Я пытаюсь написать простой генератор, который использует дерево выражений для динамической генерации метода, который сравнивает все свойства экземпляра типа со свойствами другого экземпляра этого типа. Это прекрасно работает для большинства свойств, таких как int
и string
, но не работает для DateTime?
(и, вероятно, других типов значений, допускающих значение NULL).
Метод:
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' метода 'Boolean Equals (System.Object)'
ОК, значит, обнаружена перегрузка Equals
, ожидающая object
. Так почему я не могу передать DateTime?
в него, поскольку он конвертируется в object
? Если я смотрю на Nullable<T>
, он действительно имеет переопределение Equals(object o)
.
PS : Я понимаю, что это еще не правильный генератор, так как он не может работать со null
значениями, но я вернусь к этому:)
ОБНОВЛЕНИЕ : ответ Ираклиса сработал для этой конкретной проблемы, но в итоге я выбрал гораздо более простой подход, который, на мой взгляд, достаточно: просто используйте Expression.Equal
. Я думаю, что это покрывает 99% моих дел (не уверен, сможет ли он обработать переопределение Equals
без переопределения ==
, но это нормально).