【问题标题】:How do I grab the Property name and compared value from an expression?如何从表达式中获取属性名称和比较值?
【发布时间】:2017-05-19 18:18:26
【问题描述】:

我们在工作中使用过滤器,这是一种类型

表达式 >

我们使用以下方法:

元组 SplitFilter(x => x.SurName == "Smith");

我需要创建一个以 Expression> 作为参数的方法,如上所示,并将其分解为 3 个值,一个字符串“SurName”用于属性,一个字符串“= =" 表示相等比较,字符串 "Smith" 也表示要比较的值。

我设法从中取出字符串“SurName”,但我终其一生都无法弄清楚如何确定比较类型(相等)或比较值(“Smith”)

【问题讨论】:

    标签: c# reflection properties expression func


    【解决方案1】:

    前几天搞定了。最终目标实际上是对这些值进行哈希处理,这样我们就可以从每个过滤器中得到一个哈希值。对于未来的人,我最终是如何分解的:

    private int HashFilter<T>( Expression<Func<T, bool>> filter ) {
      var param = filter.Parameters[0];
      var operation = filter.Body as BinaryExpression;
      var leftParameter = operation.Left as ParameterExpression;
      var leftIndex = operation.Left as MemberExpression;
      var type = operation.Left.GetType().FullName;
      var rightConstant = operation.Right as ConstantExpression;
      object result;
      if ( rightConstant == null ) {
        var rightMember = operation.Right as MemberExpression;
        result = Expression.Lambda( rightMember ).Compile().DynamicInvoke();
      }
      else {
        result = rightConstant.Value;
      }
      var value = result as string;
      var leftHashCode = leftParameter != null ? leftParameter.Name.GetStableHashCode() : leftIndex.Member.Name.GetStableHashCode();
      var operationHashCode = operation.NodeType.ToString().GetStableHashCode();
      unchecked {
        if ( value != null ) {
          return leftHashCode | operationHashCode | value.GetStableHashCode();
        }
        else {
          return leftHashCode | operationHashCode | result.GetHashCode();
        }
      }
    }
    

    GetStableHashCode 是以下扩展哈希算法(因为哈希字符串使用引用,所以 "Hi".GetHashCode() == "Hi".GetHashCode() 永远不会评估为真,但这个 GetStableHashCode 会。

    public static int GetStableHashCode( this string str ) {
      unchecked {
        int hash1 = (5381 << 16) + 5381;
        int hash2 = hash1;
    
        for ( int i = 0; i < str.Length; i += 2 ) {
          hash1 = ((hash1 << 5) + hash1) ^ str[i];
          if ( i == str.Length - 1 )
            break;
          hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
        }
    
        return hash1 + (hash2 * 1566083941);
      }
    }
    

    【讨论】:

      【解决方案2】:

      取自这里:https://www.codeproject.com/Questions/322211/Parsing-a-linq-expression

      static readonly List<int> data = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      
      static IEnumerable<int> SelectData(Expression<Predicate<int>> selector)
      {
          ParameterExpression param = (ParameterExpression)selector.Parameters[0];
          BinaryExpression operation = (BinaryExpression)selector.Body;
          ParameterExpression left = (ParameterExpression)operation.Left;
          ConstantExpression right = (ConstantExpression)operation.Right;
      
          Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",
                            param.Name, left.Name, operation.NodeType, right.Value);
          //...
      
          return from d in data where selector.Compile()(d) select d;
      }
      
      static void Main(string[] args)
      {
          Console.WriteLine("data = {0}", string.Join(",", SelectData(d=>d>4)));
      }
      
      Decomposed expression: d => d GreaterThan 4
      data = 5,6,7,8,9
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-21
        相关资源
        最近更新 更多