简体   繁体   中英

How to create an object with dynamic property name and parse with System.Linq.Expressions?

Based on the requirement I need to pass a dynamically generated property name for the dynamic object below.

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

Instead of State I should be able to pass any name. Here is my code so far. Everything works but I cannot figure it out how to make the property name dynamic. Something like 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;

Not sure you can do that with anonymous types, but you can do that with ExpandoObject, like this:

    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);
    }

you can to create anonymous type use LINQ from previous defined properties in some type, but you cant to create dynamic property. Use enum (california, florida and etc.) and this property's name will state.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM