Я разрабатываю механизм правил, в котором правила устанавливаются в базе данных с таким дизайном:
"PropertyName", "Operator", "PropertyValue" (например, для data.employee.salary = 10000). Это выполняется для основного класса, который имеет данные в качестве свойства, которое фактически указывает на вложенный класс с именем Data, а внутренний класс «data», в свою очередь, имеет свойство employee, которое отображается на внутренний класс Employee со свойством зарплата которая строка прямо сейчас.
Это часть кода RulesEngine, который я кодировал и использует ExpressionTrees:
// Loop through each of the rules per Ruleset and compile them against the properties of the supplied T object.
//NOTE: The values in the database column 'PropertyName' should match exactly with the properties of the T class.
rules.ForEach(rule =>
{
var genericType = Expression.Parameter(typeof(T));
// var key = MemberExpression.Property(genericType, rule.PropertyName);
var key = CreateExpression(typeof(T), rule.PropertyName); //rule.PropertyName== 'data.employee.salary'
var propertyType = GetProp(typeof(T), rule.PropertyName).PropertyType; // System.String
var value = Expression.Constant(Convert.ChangeType(rule.PropertyValue, propertyType)); //"10000"
` if (rule.Operator != ExpressionType.Lambda && rule.Operator != ExpressionType.Default) //This covers both '=' and '<>' or anything Binary-ish Operators setup in the Rules table.
{
var binaryExpression = Expression.MakeBinary(rule.Operator, key, value);
compiledExpTreeRules.Add(Expression.Lambda<Func<T, bool>>(key, genericType).Compile());
}
static LambdaExpression CreateExpression(Type type, string propertyName)
{
var param = Expression.Parameter(type, "x");
Expression body = param;
foreach (var member in propertyName.Split('.'))
{
body = Expression.PropertyOrField(body, member);
}
return Expression.Lambda(body, param);
//return MemberExpression.Property(body, propertyName);
}
Проблема, с которой я столкнулся, заключается в том, что я возвращаю Expression.Lambda из моего метода CreateExpression (). Мне пришлось написать этот метод, потому что мой входной класс T имеет вложенные классы внутри и, следовательно, свойства и правила могут быть настроены в базе данных, на уровне свойств листа внутреннего вложенного класса.
Когда я пытаюсь выполнить эту строку, выдает ошибку:
var binaryExpression = Expression.MakeBinary(rule.Operator, key, value);
Как создать двоичное выражение, когда я уже знаю лямбда-выражение, которое является параметром 'key'? Этот ключ в списке параметров MakeBinary не работает. Я также попробовал key.body, но я просто не знаю, как это сделать: 1) заставить CreateExpression () вернуть MemberExpression.Property или 2) когда он возвращает лямбда-выражение типа x => x.innnerclass1.prop1, как я могу это сделать? использовать это как «ключ» и сделать BinaryExpression? У меня есть лямбда, у меня есть оператор (исходя из БД), и у меня есть значение, но я изо всех сил пытаюсь построить из него двоичное выражение.
Заранее спасибо!