2017-09-27 5 views
3

표현식으로 제공되는 하나의 배열에서 값을 읽어야합니다. 표현식에서리스트 값을 추출하는 방법

나는이 방법

public ExpressionAnalizer<TModel> where TModel : class 
{ 
    public string BuildExpression(Expression<Func<TModel, bool>> expression) 
    { 
     if (expression?.Body is MethodCallExpression) 
      return BuildMethodCallExpression(expression);     

     throw new ArgumentException($"The expression '{expression?.Body}' is unsupported"); 
    } 

    public string BuildMethodCallExpression(Expression<Func<TModel, bool>> expression) 
    { 
     var body = expression.Body as MethodCallExpression; 
     //TODO: I can't find a property that has the values of IEnumerable 
     return null; 
    } 
} 

이 그리고이

//PersonModel is a plain class with some properties. 
var analizer= new ExpressionAnalizer<PersonModel>(""); 
var names = new List<string>() {"n1", "n2", "n3"}; 
//I want to get "Email contains ('n1', 'n2', 'n3')". I can read Email property, the call method name "Contains", but not itself values 
var response = analizer.BuildExpression(x => names.Contains(x.Email)); 

어떤 생각처럼라고? 표현식을 컴파일하려고 생각했지만 System.Runtime.CompilerServices.Closure가 private이고 사용할 수 없기 때문에 "Closure"클래스에 걸렸습니다. 그런데

, 내가

email contains ('n1','n2','n3') 

같은 문자열과 입력 매개 변수를 얻을 필요가 편집

1.0

.NET의 코어를 사용하고있어 항상해야 표현

Expression<Func<TModel, bool>> 

이것은 beca 내부적으로 사용,이 방법은 내가 expression.Body 유형을 처리하고 난 다른 사용 사례의 구현이, 내부적으로

x => x.SomeProperty == "n1" 

처럼, 어떤 표정을받을 수 있습니다. 입력 표현이 여기에

var someList = new List<string>() { "string1", "anotherString", "finalString" }; 
someObject.SomeProperty<SomeTModel>(x => someList.Contains(x.SomeProperty)) 

답변

1

당신에게 원하는 출력을 줄 것이다 ExpressionAnalizer 클래스의 전체 구현 때

사건 내가 구현할 수있는 방법을 알아낼 수 없습니다입니다.

public class ExpressionAnalizer<TModel> where TModel : class 
    { 
     public string BuildExpression(Expression<Func<TModel, bool>> expression) 
     { 
      if (expression?.Body is MethodCallExpression) 
       return BuildMethodCallExpression(expression); 

      throw new ArgumentException($"The expression '{expression?.Body}' is unsupported"); 
     } 

     public string BuildMethodCallExpression(Expression<Func<TModel, bool>> expression) 
     { 
      var body = expression.Body as MethodCallExpression; 

      //Get Method Name 
      string method = body.Method.Name; 

      //Get List of String Values 
      var methodExpression = ResolveMemberExpression(body.Object); 
      var listValues = ReadValue(methodExpression); 
      var vString = string.Format("'{0}'", string.Join("' , '", (listValues as List<string>))); 

      //Read Propery Name 
      var argExpression = ResolveMemberExpression(body.Arguments[0]); 
      var propertyName = argExpression.Member.Name; 

      return $"{propertyName} {method} ({vString})"; 

     } 

     public MemberExpression ResolveMemberExpression(Expression expression) 
     { 

      if (expression is MemberExpression) return (MemberExpression)expression; 
      if (expression is UnaryExpression) return (MemberExpression)((UnaryExpression)expression).Operand; 

      throw new NotSupportedException(expression.ToString()); 
     } 

     private object ReadValue(MemberExpression expression) 
     { 
      if (expression.Expression is ConstantExpression) 
      { 
       return (((ConstantExpression)expression.Expression).Value) 
         .GetType() 
         .GetField(expression.Member.Name) 
         .GetValue(((ConstantExpression)expression.Expression).Value); 
      } 
      if (expression.Expression is MemberExpression) return ReadValue((MemberExpression)expression.Expression); 

      throw new NotSupportedException(expression.ToString()); 
     } 

    } 

사용법 :

var analizer= new ExpressionAnalizer<PersonModel>(); 
var names = new List<string>() {"n1", "n2", "n3"}; 
var person = new PersonModel{ Email = "Email 1"}; 
var response = analizer.BuildExpression(x => names.Contains(x.Email)); 

응답 :

Email Contains ('n1' , 'n2' , 'n3') 
+0

내가 자세한 내용은 내 질문을 편집 할 수 있습니다. 기본적으로 매개 변수로 IEnumerable을 허용하는 메서드를 사용할 수 없습니다. 너 나 좀 도와 줄 수있어? –

관련 문제