如何提取在表达式< Func< T,TResult>>中使用的属性。查询和测试他们的价值? [英] How to extract properties used in a Expression<Func<T, TResult>> query and test their value?

查看:97
本文介绍了如何提取在表达式< Func< T,TResult>>中使用的属性。查询和测试他们的价值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

在上面的代码中, (10)与B(5),然后添加C(-1)。规则表示如果查询中使用的一个属性的值为-1或-2,则返回0 。因此在这个例子中,值的返回应该是-1。如果查询遵循规则,则应用对数据的查询并返回值。

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?

推荐答案

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

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

这篇关于如何提取在表达式&lt; Func&lt; T,TResult&gt;&gt;中使用的属性。查询和测试他们的价值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆