gpt4 book ai didi

c# - 如何提取 Expression> 查询中使用的属性并测试它们的值?

转载 作者:行者123 更新时间:2023-11-30 22:33:01 25 4
gpt4 key购买 nike

我需要创建一个函数来评估某些规则的查询,然后再执行它们。这是代码:

public class DataInfo
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
}

static class Program
{
static void Main()
{
var data = new DataInfo()
{
A = 10,
B = 5,
C = -1
};

// the result should be -1
int result = Calcul<DataInfo>(data, x => x.A / x.B + x.C);
}

static int Calcul<T>(T data, Expression<Func<T, int>> query)
{
// PSEUDO CODE
// if one property used in the query have a
// value of -1 or -2 then return 0
// {
// return 0;
// }

// if one property used in the query have a
// value of 0 AND it is used on the right side of
// a Divide operation then return -1
// {
// return -1;
// }

// if the query respect the rules, apply the query and return the value
return query.Compile().Invoke(data);
}
}

在前面的代码中,计算要用 A(10) 除以 B(5),然后加上 C(-1)。规则规定如果查询中使用的一个属性的值为 -1 或 -2,则返回 0。所以在这个例子中,返回值应该是-1。如果查询遵守规则,则对数据应用查询并返回值。

那么在对数据应用查询之前,如何提取查询中使用的属性并测试其中使用的值?

最佳答案

您需要使用 ExpressionVisitor 来测试属性值。下面是如何实现逻辑的示例。

using System;
using System.Linq.Expressions;
using System.Reflection;

namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main()
{
// HasDivideByZero - the result should be -1
int result1 = Calcul<DataInfo>(new DataInfo { A = 10, B = 0, C = 1 }, x => x.A / x.B + x.C);
// HasNegative - the result should be 0
int result2 = Calcul<DataInfo>(new DataInfo { A = 10, B = 5, C = -1 }, x => x.A / x.B + x.C);
// the result should be 3
int result3 = Calcul<DataInfo>(new DataInfo { A = 10, B = 5, C = 1 }, x => x.A / x.B + x.C);
}

static int Calcul<T>(T data, Expression<Func<T, int>> query)
{
if (NegativeValueChecker<T>.HasNegative(data, query))
{
return 0;
}

if (DivideByZeroChecker<T>.HasDivideByZero(data, query))
{
return -1;
}

return query.Compile().Invoke(data);
}
}

class DivideByZeroChecker<T> : ExpressionVisitor
{
private readonly T _data;
private bool _hasDivideByZero;

public static bool HasDivideByZero(T data, Expression expression)
{
var visitor = new DivideByZeroChecker<T>(data);
visitor.Visit(expression);

return visitor._hasDivideByZero;
}

public DivideByZeroChecker(T data)
{
this._data = data;
}

protected override Expression VisitBinary(BinaryExpression node)
{
if (!this._hasDivideByZero && node.NodeType == ExpressionType.Divide)
{
var rightMemeberExpression = (MemberExpression)node.Right;
var propertyInfo = (PropertyInfo)rightMemeberExpression.Member;
var value = Convert.ToInt32(propertyInfo.GetValue(this._data, null));
this._hasDivideByZero = value == 0;
}

return base.VisitBinary(node);
}
}

class NegativeValueChecker<T> : ExpressionVisitor
{
private readonly T _data;
public bool _hasNegative;

public static bool HasNegative(T data, Expression expression)
{
var visitor = new NegativeValueChecker<T>(data);
visitor.Visit(expression);

return visitor._hasNegative;
}

public NegativeValueChecker(T data)
{
this._data = data;
}

protected override Expression VisitMember(MemberExpression node)
{
if (!this._hasNegative)
{
var propertyInfo = (PropertyInfo)node.Member;
var value = Convert.ToInt32(propertyInfo.GetValue(this._data, null));
this._hasNegative = value < 0;
}

return base.VisitMember(node);
}
}

class DataInfo
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
}
}

关于c# - 如何提取 Expression<Func<T, TResult>> 查询中使用的属性并测试它们的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8508316/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com