ParameterExpression типа «System.Int32» нельзя использовать для параметра делегата типа «System.String» - PullRequest
3 голосов
/ 29 марта 2012

Я создаю общий установщик, используя дерево выражений, и вот мой код

public Expression<Action<T,string>> GetAction<T>(string fieldName)
{
    ParameterExpression targetExpr = Expression.Parameter(typeof(T), "Target");  
    MemberExpression fieldExpr = Expression.Property(targetExpr, fieldName);    
    ParameterExpression valueExpr = Expression.Parameter(fieldExpr.Type, "value"); 
    UnaryExpression valueCast = (!fieldExpr.Type.IsValueType) 
                              ? Expression.TypeAs(valueExpr, fieldExpr.Type) 
                              : Expression.Convert(valueExpr, fieldExpr.Type);
    BinaryExpression assignExpr = Expression.Assign(fieldExpr, valueCast);    
    return Expression.Lambda<Action<T, string>>(assignExpr, targetExpr, valueExpr);
}

Я не вызываю .Compile() в вышеприведенном методе, потому что я хочу исследовать построенное выражение.

И мой объект

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

}

Я называю этот метод следующим образом

var lastname = GetAction<Person>("FirstName");
var age = GetAction<Person>("Age");

lastname.Compile()(p, "Solutions");
age.Compile()(p, "10");

Причина, по которой я передаю возраст как строку, заключается в том, что я получу это значениеиз XML.

Создает действие для FirstName безо всякой ошибки, тогда как для Age оно дует.

В этой строке происходит ошибка для Age:

 return Expression.Lambda<Action<T, string>>(assignExpr, targetExpr, valueExpr);

Ошибка:

ParameterExpression типа 'System.Int32' нельзя использовать для параметра делегата типа 'System.String'

Можно ли что-то сделать с динамическим..?

Я надеюсь, что у кого-нибудь будет какое-то решение.Спасибо

Ответы [ 2 ]

3 голосов
/ 29 марта 2012

Вы должны позвонить Convert.ChangeType для преобразования типа:

public static Expression<Action<T, string>> GetAction<T>(string fieldName)
{
    ParameterExpression targetExpr = Expression.Parameter(typeof(T), "Target");
    MemberExpression fieldExpr = Expression.Property(targetExpr, fieldName);
    ParameterExpression valueExpr = Expression.Parameter(typeof(string), "value");
    MethodCallExpression convertExpr = Expression.Call(typeof(Convert),
        "ChangeType", null, valueExpr, Expression.Constant(fieldExpr.Type));
    UnaryExpression valueCast = Expression.Convert(convertExpr, fieldExpr.Type);
    BinaryExpression assignExpr = Expression.Assign(fieldExpr, valueCast);
    return Expression.Lambda<Action<T, string>>(assignExpr, targetExpr, valueExpr);
}
2 голосов
/ 29 марта 2012

Проблема заключается в следующем:

Вы возвращаете Expression<Action<T,string>>, что в основном означает, что результатом будет string.С другой стороны, вы передаете «Возраст» как имя поля, которое должно возвращать действие.Однако Age относится к типу int, а не string.

. Вы можете решить это по крайней мере двумя способами:

  1. Добавьте второй универсальный параметр к вашему GetAction метод, который указывает тип возвращаемого значения.
  2. Добавьте вызов к ToString возвращаемого свойства в выражение.
...