如何创建具有动态属性名称的对象并使用System.Linq.Expressions进行解析?

时间:2016-05-08 14:49:39

标签: c# linq lambda

根据要求,我需要为下面的动态对象传递动态生成的属性名称。

var dynamicObj = new { State = "Caifornia" };

而不是国家我应该能够传递任何名称。到目前为止,这是我的代码。一切正常,但我无法弄清楚如何使属性名称动态。像var dynamicObj = new { "State" = "Caifornia" };

这样的东西
var rule = new Rule("State", "NotEqual", "Florida");
var dynamicObj = new { State = "Caifornia" };
var expression = Expression.Parameter(dynamicObj.GetType(), "State");
var property = Expression.Property(expression, "State");
var propertyType = dynamicObj.GetType().GetProperty(rule.MemberName).PropertyType;

var isValid = false;
ExpressionType tBinary;

if (Enum.TryParse(rule.Operator, out tBinary))
{
      var right = Expression.Constant(Convert.ChangeType(rule.TargetValue, propertyType));
      var result = Expression.MakeBinary(tBinary, property, right);
      var func = typeof(Func<,>).MakeGenericType(dynamicObj.GetType(), typeof(bool));
      var expr = Expression.Lambda(func, result, expression).Compile();
      isValid = (bool)expr.DynamicInvoke(dynamicObj);
}

return isValid;

2 个答案:

答案 0 :(得分:1)

不确定您是否可以使用匿名类型执行此操作,但您可以使用ExpandoObject执行此操作,如下所示:

    var rule = new Rule("State", "NotEqual", "Florida");            
    var dynamicObj = (IDictionary<string, object>) new ExpandoObject();            
    dynamicObj.Add("State", "California");
    var expression = Expression.Parameter(typeof(object), "arg");
    // create a binder like this
    var binder = Microsoft.CSharp.RuntimeBinder.Binder.GetMember(CSharpBinderFlags.None, "State", null, new CSharpArgumentInfo[] {
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
        });
    // define dynamic property accessor
    var property = Expression.Dynamic(binder, typeof(object), expression);        
    // the rest as usual
    var isValid = false;
    ExpressionType tBinary;

    if (Enum.TryParse(rule.Operator, out tBinary))
    {
        var right = Expression.Constant(rule.TargetValue);
        var result = Expression.MakeBinary(tBinary, property, right);
        var func = typeof(Func<,>).MakeGenericType(dynamicObj.GetType(), typeof(bool));
        var expr = Expression.Lambda(func, result, expression).Compile();
        isValid = (bool)expr.DynamicInvoke(dynamicObj);
    }

答案 1 :(得分:0)

您可以使用之前在somoe类型中定义的属性创建anonimous类型使用linq,但是您无法创建动态属性。使用enum(加利福尼亚州,佛罗里达州等),这个属性的名称将说明。