2016-03-25 21 views
1

Bir kural motoru için dinamik olarak ifadeler oluşturmaya çalışıyorum ve iç içe türlere ve özelliklere izin vermeye çalışana kadar işler çok iyi gidiyordu işlenen olarak belirtilmelidir. Örnek:Expression.PropertyOrField "dize özelliği için" System.String "türünde bir üye döndürmez"

ExpressionBuilder

public Expression BuildExpression<T>(string propertyName, Enums.Operator ruleOperator, object value, ParameterExpression parameterExpression) 
    { 
     ExpressionType expressionType = new ExpressionType(); 
     Expression body = parameterExpression; 

     foreach (var member in propertyName.Split('.')) 
     { 
      body = MemberExpression.Property(body, member); 
     } 

     var leftOperand = MemberExpression.PropertyOrField(body, propertyName); 
     var rightOperand = Expression.Constant(Convert.ChangeType(value, value.GetType())); 
     FieldInfo fieldInfo = expressionType.GetType().GetField(Enum.GetName(typeof(Enums.Operator), ruleOperator)); 
     var expressionTypeValue = (ExpressionType)fieldInfo.GetValue(ruleOperator); 

     return CastBuildExpression(expressionTypeValue, value, leftOperand, rightOperand); 
    } 

RuleEngine

public Func<T, bool>[] CombineRules<T>(Criterion[] criteria) 
    { 
     List<Func<T, bool>> list = new List<Func<T, bool>>(); 
     foreach (var criterion in criteria) 
     {      
      ExpressionBuilder expressionBuilder = new ExpressionBuilder(); 
      var param = Expression.Parameter(typeof (T)); 
      Expression expression = expressionBuilder.BuildExpression<T>(criterion.PropertyName, 
        criterion.Operator_, criterion.Value, param); 
      Func<T, bool> func = Expression.Lambda<Func<T, bool>>(expression, param).Compile(); 
      list.Add(func); 
     } 

     return list.ToArray(); 
    } 

Kriter

public class Criterion 
{ 
    private bool propertySet; 
    public string PropertyName { get; set; } 
    public Enums.Operator Operator_ { get; set; } 
    public object Value { get; set; } 

MemberModel

public class MemberModel 
{ 
    public string UserName{ get; set; } 
    public PersonalDetailsModel PersonalDetails {get; set;} 
} 

PersonalDetailsModel

public class PersonalDetailsModel 
{ 
    public int PersonalDetailsId { get; set; } 
    public string Firstname { get; set; } 
    public string Lastname { get; set; } 
    public string Middlename { get; set; } 
    public string DateOfBirth { get; set; } 
    public string GenderType { get; set; } 
    public string SalutationType { get; set; } 
} 

I ruleEngine.CombineRules bir sol işlenen, yani PropertyName = "PersonalDetails.FirstName" iç içe özelliklerinde geçmek deneyin zaman bir sorun ortaya çıkar (kriterleri .Sıralamak());

"PersonalDetails.Firstname 'türünün bir üyesi değil,' System.String '" alıyorum. Bir süredir bunun üzerinde sıkışıp kaldım, buna neden olan herhangi bir fikir var mı?

Herhangi bir yardım büyük memnuniyetle karşılanacaktır.

cevap

2

İşte

Expression body = parameterExpression; 

    foreach (var member in propertyName.Split('.')) 
    { 
     body = MemberExpression.Property(body, member); 
    } 

zaten mülkiyet yolunu işlenmiş, bu nedenle bu

var leftOperand = MemberExpression.PropertyOrField(body, propertyName); 

hiçbir anlam ve istisna kaynağıdır. Örneğin, body, p.PersonalDetails.FirstName (String) gibi bir şey içeriyor ve yukarıdaki satır p.PersonalDetails.FirstName.PersonalDetails.FirstName gibi bir şey oluşturmaya çalışıyor. Bunun yerine, var leftOperand = body; kullanın.

Basit

var leftOperand = propertyName.Split('.') 
    .Aggregate((Expression)parameterExpression, Expression.PropertyOrField); 
+0

Aman, ne saçma gözetim kullanarak bütün özellik yolu işleme kısaltabilir. Kanlı Cumalar. Çok teşekkür ederim! – shanomacadaemia

İlgili konular