c# - 反射 v 表达

标签 c# lambda expression-trees

我正在查看another question说明了表达式如何比反射快得多,因为它可以预编译为 IL。

不过我不太确定如何使用它。以下是值对象(在 DDD 意义上)的基类中使用的一些代码,其中基本思想是使用所有公共(public)属性的值来确定通过反射获得的相等性。通过使用这个基类,您不需要为具有值对象的子类实现相等。

protected virtual bool HasSameObjectSignatureAs(BaseObject compareTo) 
{
var signatureProperties = GetType().GetProperties();
foreach (var property in signatureProperties)
{
    var valueOfThisObject = property.GetValue(this, null);
    var valueOfCompareTo = property.GetValue(compareTo, null);

    if (valueOfThisObject == null && valueOfCompareTo == null) {
        continue;
    }

    if ((valueOfThisObject == null ^ valueOfCompareTo == null) ||
        (!valueOfThisObject.Equals(valueOfCompareTo))) {
            return false;
    }
}

如何使用表达式重写此代码?

干杯,
贝里尔

最佳答案

您可以通过为要比较的每个属性构建嵌套的 And 表达式来实现此目的:

protected Expression<Func<BaseObject, bool>> CreatePropertiesEqualExpression(BaseObject other)
{
    if (! other.GetType().IsSubclassOf(this.GetType())) throw new ArgumentException();

    var properties = this.GetType().GetProperties();
    Expression trueExpr = Expression.Constant(true);
    Expression thisExpr = Expression.Constant(this);
    ParameterExpression paramExpr = Expression.Parameter(typeof(BaseObject), "compareTo");
    Expression downCastExpr = Expression.Convert(paramExpr, other.GetType());

    MethodInfo eqMethod = typeof(object).GetMethod("Equals", BindingFlags.Public | BindingFlags.Static);

    Expression propCompExpr = properties.Aggregate(trueExpr, (expr, prop) =>
    {
        Expression thisPropExpr = Expression.Property(thisExpr, prop);
        Expression compPropExpr = Expression.Property(downCastExpr, prop);
        Expression eqExpr = Expression.Call(null, eqMethod, Expression.Convert(thisPropExpr, typeof(object)), Expression.Convert(compPropExpr, typeof(object)));

        return Expression.And(expr, eqExpr);
    });

    return Expression.Lambda<Func<BaseObject, bool>>(propCompExpr, paramExpr);
}

然后您可以像这样使用它:

public class SubObject : BaseObject
{
    public int Id { get; set; }
    public string Name { get; set; }
    private Func<BaseObject, bool> eqFunc;

    public bool IsEqualTo(SubObject other)
    {
        if(this.eqFunc == null)
        {
            var compExpr = this.CreatePropertiesEqualExpression(other);
            this.eqFunc = compExpr.Compile();
        }
        return this.eqFunc(other);
    }
}

关于c# - 反射 v 表达,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12582707/

相关文章:

javascript - 如何使用 FP 的 compose() javascript 将两个函数组合成一个函数?

c# - 如何为 Windows 应用程序创建更新补丁

c# - 从双映射

c# - 如何使用linq过滤类列表中的列表?

c++ - 向数学解析器添加条件和函数

c# - ExpressionTree 重写 - 参数 'x' 不在范围内

c# - 检查表达式中的 Null

c# - 我什么时候应该使用延迟加载以及它应该延迟到什么程度

c# - 如何将以下嵌套 SQL 实现为 Lambda 语句

c# - 在 BackgroundWorker 中内联一些事件?