2010-12-10 18 views
3

Je veux définir une fonction comme la fonction de modèle d'extension MVC TextBoxFordéfinir .net fonction qui prend une expression lambda

La chose intéressante pour cette fonction est que je n'ai pas de spécifier un type de TProperty. Comment puis-je définir cela dans ma définition de fonction.

Mon apparence de code comme:

public class Helper<TItem> 
{ 
    public string GetMemberName(Expression<Func<TItem, TProperty>> expression) 
    { 
     ... returns TProperty.Name 

    } 
} 

Le problème réel est que cela ne compile pas ... parce qu'il ne peut pas trouver le type de TProperty. Le résultat que je veux est de définir la classe une fois avec un type ... et ensuite utiliser la fonction GetMemberName pour obtenir le nom de chaque membre comme dans le cadre MVC. Je ne veux pas être forcé de spécifier le type TProperty lorsque j'écris le code. Fondamentalement, il peut s'agir de n'importe quel objet.

Merci,

Radu

+0

Mec voir ma réponse, peut-être obtenir votre code plus élégant. –

Répondre

3

C'est ce que vous avez besoin:

public class Helper<TItem> 
{ 
    public string GetMemberName<TProperty>(Expression<Func<TItem, TProperty>> expression) 
    { 
     return string.Empty; // I didn't implement it 
    } 
} 

Juste ap pend <TProperty> à votre nom de méthode pour le rendre générique. Et le type de TProperty peut être déduit de l'expression fournie, donc vous ne devez pas spécifier le type lors de l'utilisation, peut être simplement:

Helper<Employee> h = new Helper<Employee>(); 
h.GetMemberName(e=>e.Name); //if Employee has such a property 
+0

Merci beaucoup ... vous avez sauvé ma journée :) Comment Linq peut-il déduire que je veux une propriété de l'objet là-bas? Est-ce une convention? –

+0

@Radu D: Si vous voulez en savoir plus sur l'inférence de type, jetez un oeil à 'C# Language Specification §7.5.2 Type inference'. –

0

Vous pouvez utiliser la classe ModelMetaData pour extraire des informations de la Expression.

public string GetMemberName<TProperty>(Expression<Func<TItem, TProperty>> expression) { 
    var meta = ModelMetaData.FromLambdaExpression(expression, null); 
    return meta.PropertyName; // Or something else 
} 
1

fonction suivante retourne le nom de toute propriété qui est passé à l'aide d'une expression lambda:

public static string Property<T>(Expression<Func<T>> e) 
    { 
     var member = (MemberExpression)e.Body; 
     return member.Member.Name; 
    } 
+0

Il fait le travail juste pour les types de données primitifs AFAIK –

+0

Il n'a rien à voir avec 'Type' d'une propriété mais' Name' d'une propriété. – decyclone

0

j'ai écrit cette fonction une fois, mais je ne me souviens pas exactement. Mais d'abord changer la signature du délégué à cette Func<T, object>, puis pour de simples types de données à l'organisme d'expression et de le jeter à MemberExpression et obtenir si le membre accessible est complexe le nom du premier paramètre

vous devez lancer le corps de l'expression à UnaryExpression prendre le premier paramètre et le transformer en MemberExpression et faire ce que vous avez fait dans la première étape.

Jouer avec QuickWatch lors du débogage de la fonction pourrait vous conduire à la solution. Il est utile de mentionner que la lecture du HtmlHelper dans le code MVC pourrait être utile.

EDIT: Environ rappeler

La meilleure approche est d'écrire cette fonction Méthode d'extension (avec la contrainte sur le type, le cas échéant, si vous voulez) afin que fournir le type d'employé est pas plus nécessaire, parce que c'est déduit de l'utilisation.

Ainsi, votre fonction est comme ça:

public static class Helper 
{ 
    public static string Item<TItem,TMember>(this TItem obj, Expression<Func<TItem, TMember>> expression) 
    { 
     if (expression.Body is MemberExpression) 
     { 
      return ((MemberExpression)(expression.Body)).Member.Name; 
     } 
     if(expression.Body is UnaryExpression) 
     { 
      return ((MemberExpression)((UnaryExpression)(expression.Body)).Operand).Member.Name; 
     } 
     throw new InvalidOperationException(); 
    } 
} 

Ainsi, votre code sera beaucoup plus propre

Employee emp = new Employee(); 
emp.Item(o=>o.Name); 

Espoir vous aide