我正在看一個簡單的規則引擎http://netmatze.wordpress.com/2012/01/22/building-a-rule-engine-in-c/,我正在做一些與此非常相似的事情。我有一個看起來像兩個類:用於深度屬性比較的表達式構建器
class A
{
public List<B> ListB { get; set; }
}
Class B
{
public int ID { get; set; }
}
用我的規則集看起來像:
List<Rule> rules = new List<Rule>{
new Rule("listB", ExpressionType.Loop, 1, "ID")
};
我試圖建立的表達,主要看類的屬性數組listB,循環播放camparing各項目的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));
我的問題是:
- 如果列表 中的任何項目符合條件,我如何獲得此函數返回true/false。
- 一旦比較了所有列表項(並且它們都不匹配),如何防止Expression.Loop 停止循環?
感謝您的幫助。
肯定我不能用那樣的LINQ聲明(儘管我很想)的東西。這個代碼所在的方法並不瞭解ListB。它只知道A類和B類的屬性名稱以及通過通用T傳遞的A類。 該代碼所在的方法如下所示: public Func BuildExpression (string propertyName,ExpressionType ruleOperator,object value,ParameterExpression參數表達式,字符串innerPropertyName) { –
riververy
}無論何時您在C#中編寫數據庫查詢,都會隱式創建這樣的表達式樹。這當然是可能的。請注意,該擴展方法等同於靜態方法調用(請參閱編輯)。我明白,沒有任何標識符名稱是靜態的。我只是試圖舉一個你必須用表達式樹建立的結構的例子。大多數C#表達式都可以轉換爲表達式樹。例如,'Enumerable.Any'只是一個'Expression.Call'。這有幫助嗎? – usr