我需要生成表达式树,而不是检查两个对象(参数)是否相等。我知道这些对象会有属性,所以我必须比较它们的值,怎么做?
所以我有obj1
,obj2
和我需要检查属性名称的字符串数组。
我是这样看的:
var leftObject = E.Parameter(typeof (object), "leftObject");
var rightObject = E.Parameter(typeof (object), "rightObject");
var properties = E.Parameter(typeof (string[]), "properties");
var i = E.Parameter(typeof(int), "i");
var equal = E.Parameter(typeof (bool), "equal");
var body = E.Block
(
new[] { properties, i},
E.Assign(properties,E.Constant(props)),
E.Assign(i,E.Constant(0)),
E.Assign(equal,E.Constant(true)),
E.Loop
(
E.Property(leftObject,props[i]) == E.Property(rightObject,props[i])
)
);
如何在Loop中逐个实现对属性的访问?
P.S。 E
是我Expression
的别名。
答案 0 :(得分:3)
答案 1 :(得分:2)
您应该使用反射来发现您想要的属性,然后基本上创建一大系列的AndAlso表达式。 e.g。
public static Func<T, T, bool> BuildStructuralComparerDelegate<T>() where T:class
{
var left = Expression.Parameter(typeof(T), "left");
var right = Expression.Parameter(typeof(T), "right");
var referenceEquals = typeof(object).GetMethod("ReferenceEquals");
Expression expression = Expression.AndAlso(
Expression.Not(
Expression.Call(
null,
referenceEquals,
left,
Expression.Default(typeof(T))
)
),
Expression.Not(
null,
Expression.Call(
referenceEquals,
right,
Expression.Default(typeof(T))
)
)
);
Array.ForEach(typeof(T).GetProperties(),property =>
expression = Expression.AndAlso(
expression,
Expression.Equal(
Expression.Property(left, property),
Expression.Property(right, property)
)
)
);
var lambdaExp = Expression.Lambda<Func<T, T, bool>>(
Expression.OrElse(
Expression.Call(
null,
referenceEquals,
left,
right
),
expression
),
left,
right
);
return lambdaExp.Compile();
}
以上代码仅适用于类,创建一个大致
的表达式(left,right)=> object.ReferenceEquals(left,right) || (left != null && right != null && left.Property1 == right.Property1 && left.Property2 == right.Property2 && ... && left.PropertyN == right.PropertyN);
这不是一个完整的解决方案,因为它假设您想要比较所有属性,并且您的所有属性都是可读的,但它应该让您走上正轨。如果您关心这些事情,它也兼容.NET 3.5。
答案 2 :(得分:1)
您可以使用反射来完成此操作。
bool eq = true;
foreach (string prop in PropertiesYouWantToCheck){
PropertyInfo propInfo = obj1.GetType().GetProperties().Single(x => x.Name == prop);
if(propInfo.GetValue(obj1, null) != propInfo.GetValue(obj2, null)){
eq = false;
break;
}
}
如果使用上述方法,请确保将字符串转换为字符串而不是对象。
string[] props = null;
var leftObject = Expression.Parameter(typeof(object), "leftObject");
var rightObject = Expression.Parameter(typeof(object), "rightObject");
var equal = Expression.Variable(typeof(bool), "equal");
var lbl = Expression.Label();
var returnTarget = Expression.Label();
var body = Expression.Block
(
typeof(bool),
equal,
Expression.Assign(equal, Expression.Constant(true)),
Expression.Block(
props.Select(property =>
Expression.IfThen(
Expression.NotEqual(Expression.Property(leftObject, property),
Expression.Property(rightObject, property)),
Expression.Block(
Expression.Assign(equal, Expression.Constant(false)),
Expression.Goto(lbl)
)
)
)
),
Expression.Label(lbl),
Expression.Return(returnTarget, equal, typeof(bool)),
Expression.Label(returnTarget)
);