如何提取表达式>中使用的属性查询并测试它们的价值?

发布于 2024-12-21 08:35:18 字数 1254 浏览 0 评论 0 原文

我需要创建一个函数来在执行某些规则之前评估它们的查询。代码如下:

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。如果查询遵循规则,则对数据应用查询并返回值。

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

I need to create a function to evaluate queries for some rules before executing them. Here's the code:

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);
    }
}

In the previous code, the calcul want to divide A(10) with B(5) and then add C(-1). The rules said that if one property used in the query have a value of -1 or -2, return 0. So in this example, the value return should be -1. If the query respect the rules, then apply the query on the data and return the value.

So how can i extract the properties used in the query and test the value used in them before appying the query on the data?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

胡渣熟男 2024-12-28 08:35:18

您需要使用 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; }
    }
}

You need to use an ExpressionVisitor to test the property values. Here is an example of how you could implement the logic.

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; }
    }
}
夜夜流光相皎洁 2024-12-28 08:35:18

查看 Moq 的来源 - http://code.google。 com/p/moq/

Get a look at the source of Moq - http://code.google.com/p/moq/.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文