ParameterExpression di tipo 'System.Int32' non può essere utilizzato per il parametro delegato di tipo 'System.String'

c# delegates dynamic expression-trees generics

Domanda

Sto creando un setter generale usando l'albero delle espressioni e qui c'è il mio codice

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

Non chiamo .Compile() nel metodo precedente perché voglio esaminare l'espressione che costruisce.

E il mio obiettivo è

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

}

Chiamo il metodo in questo modo

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

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

Il motivo per cui ho passato l'età come stringa è che otterrò questo valore da XML.

Sta creando Action for FirstName senza alcun errore mentre per Age soffia.

L'errore si verifica in questa riga per l' Age :

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

Errore:

ParameterExpression di tipo 'System.Int32' non può essere utilizzato per il parametro delegato di tipo 'System.String'

Posso fare qualcosa con dinamica ..?

Spero che qualcuno abbia qualche soluzione. Grazie

Risposta accettata

Dovresti chiamare Convert.ChangeType per la conversione del tipo:

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

Risposta popolare

Il problema è il seguente:

Si sta restituendo Expression<Action<T,string>> , che in pratica significa che il risultato sarà una string . D'altra parte, stai passando in "Età" come nome del campo che l'azione dovrebbe restituire. Age tuttavia è di tipo int , non di string .

Puoi risolverlo in almeno due modi:

  1. Aggiungi un secondo parametro generico al metodo GetAction che specifica il tipo restituito.
  2. Aggiungi una chiamata a ToString sulla proprietà restituita all'espressione.


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché