ParameterExpression des Typs 'System.Int32' kann nicht für den Delegate-Parameter 'System.String' verwendet werden

c# delegates dynamic expression-trees generics

Frage

Ich erstelle einen allgemeinen Setter mit Ausdrucksbaum und hier ist mein Code

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

Ich rufe .Compile() in der obigen Methode nicht auf, weil ich den Ausdruck untersuchen möchte, den es erstellt.

Und mein Objekt ist es

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

}

Ich nenne die Methode so

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

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

Der Grund, warum ich das Alter als String übergebe, ist, dass ich diesen Wert von XML bekommen werde.

Es erstellt Aktion für FirstName ohne Fehler, während für Age es bläst.

In dieser Zeile für Age Fehler auf:

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

Error:

ParameterExpression des Typs 'System.Int32' kann nicht für den Delegate-Parameter 'System.String' verwendet werden

Kann ich etwas mit dynamischen machen ..?

Ich hoffe, dass jemand eine Lösung haben wird. Vielen Dank

Akzeptierte Antwort

Sie sollten Convert.ChangeType für die Typkonvertierung aufrufen:

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

Beliebte Antwort

Das Problem ist folgendes:

Sie geben einen Expression<Action<T,string>> , was im Grunde bedeutet, dass das Ergebnis eine string . Auf der anderen Seite geben Sie "Alter" als Name des Feldes ein, das die Aktion zurückgeben soll. Age jedoch vom Typ int , nicht string .

Sie können dies auf mindestens zwei Arten lösen:

  1. Fügen Sie Ihrer GetAction Methode einen zweiten generischen Parameter GetAction , der den Rückgabetyp angibt.
  2. Fügen Sie ToString einen Aufruf für die zurückgegebene Eigenschaft zu dem Ausdruck hinzu.


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow