2010-09-06 12 views
3

Ce qui suit fonctionne, mais mes Body.NodeType changements à Convertir, au lieu de MemberAccess qui est un problème lors de l'obtention ModelMetadata.FromLambdaExpression:Comment convertir Expression <Func <T, TProperty >> à l'expression <Func <T, TNewProperty >>

private Expression<Func<TModel, TNewProperty>> ConvertExpression<TProperty, TNewProperty>(Expression<Func<TModel, TProperty>> expression) 
{ 
    Exression converted = Expression.Convert(expression.Body, typeof(TNewProperty)); 
    var result = Expression.Lambda<Func<TModel, TNewProperty>>(converted, expression.Parameters); 
    return result; 
} 

Dans le contexte d'un ASP.NET MVC 2.0, j'ai mon propre EditorFor:

public MvcHtmlString EditorFor<TProperty>(Expression<Func<TModel, TProperty>> expression) 

Le EditorFor délègue ensuite l'appel interne, en fonction des métadonnées, des méthodes spécifiques, ex:

public DecimalTextBox DecimalTextBoxFor(Expression<Func<TModel, decimal?>> expression) 

Le DecimalTextBox a une propriété de valeur de type décimal ?, donc je veux le mettre:

decimalTextBox.Value(expression.Compile()(ViewData.Model)); 

Appelez le formulaire EditorFor pour DecimalTextboxFor ne compile pas parce que les types ne correspondent pas, et c'est pourquoi j'ai besoin de la conversion.

code ci-dessus, fait la conversion, mais parce que le Expression.Body.NodeType est modifié, le ModelMetadata.FromLambdaExpression ne fonctionne pas, parce que le type d'expression doit être un ArrayIndex, Appel, MemberAccess ou paramètre. Convert n'est pas accepté.

Ma solution est en train de changer la DecimalTextBoxFor dans:

public DecimalTextBox DecimalTextBoxFor(Expression<Func<TModel, TProperty>> expression) 

et convertir la valeur à l'intérieur il y a:

decimalTextBox.Value((decimal?) Convert.ChangeType(expression.Compile()(ViewData.Model), typeof(decimal?))); 

Une autre conversion qui fonctionne en partie est:

private Expression<Func<TModel, TNewProperty>> ConvertExpression<TProperty, TNewProperty>(Expression<Func<TModel, TProperty>> expression) 
{ 
    Expression<Func<TModel, TNewProperty>> convertedExpression = expression as Expression<Func<TModel, TNewProperty>>; 
} 

Mais la conversion de différents types de valeurs (ex: simple à double) ne fonctionne pas bien sûr.

J'espérais convertir l'expression elle-même ...

+0

Je ne comprends pas la question. Vous obtenez un Convert parce que vous le faites. – leppie

+0

Le problème est que l'expression.Body.NodeType change. Existe-t-il un moyen de convertir sans avoir une expression différente.Body.NodeType? – Linefeed

Répondre

1

Malheureusement, ce n'est pas possible sans changer la NodeType du Body. L'expression Convert est un type d'expression distinct et représente une opération réelle. Afin de réaliser ce que vous essayez de réaliser, cette opération doit être la "première" opération, c'est-à-dire le nœud le plus haut dans l'arbre d'expression.

Je pourrais être en mesure de fournir une solution de contournement si vous expliquez pourquoi vous pensez que vous avez besoin du NodeType pour rester les mêmes. Sémantiquement cela n'a pas de sens: le Body de l'ancienne expression représente une opération spécifique, et votre nouveau Body représente une opération différente (à savoir, l'opération d'origine suivie de Convert). Vous ne pouvez pas vous attendre à représenter l'ancienne opération et à renvoyer le résultat de la nouvelle opération.