2014-03-27 5 views
2

간단한 규칙 엔진 http://netmatze.wordpress.com/2012/01/22/building-a-rule-engine-in-c/을보고 있었는데이 작업과 매우 유사합니다.깊은 속성 비교를위한 표현식 작성기

List<Rule> rules = new List<Rule>{ 
     new Rule("listB", ExpressionType.Loop, 1, "ID") 
    }; 

나는 기본적으로 클래스에서이 각각 camparing 프로퍼티 listB, 루프를 찾기 위해 표현을 구축하기 위해 노력하고있어 내 규칙 세트처럼 보이는으로

class A 
    { 
     public List<B> ListB { get; set; } 
    } 

    Class B 
    { 
     public int ID { get; set; } 
    } 

: 나는 같이 두 개의 클래스가 항목의 ID 속성 중 적어도 하나가 1인지 확인하십시오.이 작업을 수행하는 방법에 문제가 있습니다. 나는 현재 이와 비슷한 것을 가지고있다. (나는 하드 코딩 된 값을 가지고 있지만 가능한 한 많이 제네릭으로 바뀔 것이다.)

var parameterExpression = Expression.Parameter(typeof(A)); 
    var listB = MemberExpression.Property(parameterExpression, "ListB"); 
    var leftOperand = MemberExpression.Property(Expression.Parameter(typeof(B)), "ID"); 
    var rightOperand = Expression.Constant(1); //1 
    var found = Expression.Variable(typeof(bool), "found"); 

    return Expression.Lambda<Func<T, bool>>(
      Expression.Block(
       listB, 
       found, 
       Expression.Loop( 
       Expression.Block(
        Expression.IfThen(
        Expression.Equal(
         leftOperand, 
         rightOperand 
        ),//equal 
        Expression.Assign(
         found, 
         Expression.Constant(true) 
        )//set to true 
       )      
       )//block 
      )//loop 
      ), 
      A 
    ).Compile(); 

내가 지금처럼 내 개체에 설정된 규칙 호출 될 겁니다 :

Engine ruleEngine = new Engine(); 
    var compiledRules = rules.Select(r => ruleEngine.CompileRule<A>(r)).ToList(); 
    var result = compiledRules.All(rule => rule(objA)); 

내 질문

은 다음과 같습니다

  1. 을이 표현은 내가 예외를 컴파일 얻을 작동하지 않습니다 목록 중 하나가 조건과 일치하면 true/false를 반환하는 방법을이 함수에서 어떻게 얻습니까?
  2. Expression.Loop 은 모든 목록 항목이 비교되고 ( 이 일치하지 않음) 반복되는 것을 어떻게 막을 수 있습니까?

도움 주셔서 감사합니다.

답변

1

루프를 사용해야하는 이유는 무엇입니까? C#에서 체크를 코딩했다면 루프를 사용하지 않을 것입니다. Enumerable.Any을 사용하십시오.

A a; 
return a.ListB.Any(b => b.ID == 1); 

이이 변환됩니다 : : 그래서 다음 식을 생성

A a; 
return Enumerable.Any(a.ListB, b => b.ID == 1); 

이 식 트리로 쉽게 번역입니다.

+0

확신 내가 그런 LINQ 문을 사용할 수 없습니다 당신의 ruleOperator 및 값을 사용하여 뭔가

var childProperty = parameter.Type.GetProperty(properties[0]); var left = Expression.Property(parameter, childProperty); var right = Expression.Constant(test, typeof(int)); navigationPropertyPredicate = Expression.Equal(left, right); resultExpression = MakeLambda(parameter, navigationPropertyPredicate); 

. 이 코드가있는 메서드는 ListB에 대해 알지 못합니다. 공공 Func을 BuildExpression (문자열 propertyName 형식, ExpressionType의 ruleOperator, 개체 값, ParameterExpression : 그것은 단지 클래스 A와 B와 코드가 같은 외모에 일반적인 T. 방법을 통해를 통해 전달되는 클래스 A에 대한 속성 이름을 알고있다 parameterExpression, string innerPropertyName) { – riververy

+0

C#에서 데이터베이스 쿼리를 작성할 때마다 암시 적으로 그런 식 트리가 만들어집니다. 확실히 가능합니다. 이 확장 메소드는 정적 메소드 호출과 동일합니다 (편집 참조). 어떤 식별자 이름도 정적으로 알려지지 않음을 이해합니다. 방금 표현식 트리를 사용하여 빌드해야하는 구조의 예제를 제공하려고했습니다. 대부분의 C# 표현식은 표현식 트리로 정확하게 변환 가능합니다. 예를 들어,'Enumerable.Any'는 단지'Expression.Call'입니다. 그게 도움이 되니? – usr

0

내가 마지막으로 한 말은 another question에 대한 제안 된 접근 방식을 사용할 수있는 것처럼 들립니다. 이 부분을 교체합니다 (I가 사랑에도 불구하고)