本文介绍了如何提取在Expression< Func< T,TResult& gt;中使用的属性查询并测试其价值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

在前面的代码中,计算对象想将A(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; }
    }
}

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

10-30 01:26