Il y a eu beaucoup de sentiment d’inclure un nameof
opérateur en C #. Comme exemple de fonctionnement de cet opérateur, nameof(Customer.Name)
renverrait la chaîne "Name"
.
J’ai un object de domaine. Et je dois le lier. Et j’ai besoin de noms de propriétés en tant que chaînes. Et je veux qu’ils soient en sécurité.
Je me souviens d’avoir nameof
une solution de contournement dans .NET 3.5 qui fournissait les fonctionnalités de nameof
et des expressions lambda impliquées. Cependant, je n’ai pas pu localiser cette solution de contournement. Quelqu’un peut-il me fournir cette solution?
Je suis également intéressé par un moyen de mettre en œuvre la fonctionnalité nameof
dans .NET 2.0 si cela est possible.
Ce code fait essentiellement cela:
class Program { static void Main() { var propName = Nameof.Property(e => e.Name); Console.WriteLine(propName); } } public class Nameof { public static ssortingng Property(Expression> expression) { var body = expression.Body as MemberExpression; if(body == null) throw new ArgumentException("'expression' should be a member expression"); return body.Member.Name; } }
(Bien sûr c’est du code 3.5 …)
Alors que reshefm et Jon Skeet montrent la bonne façon de le faire en utilisant des expressions, il convient de noter qu’il existe un moyen moins coûteux de le faire pour les noms de méthode:
Enveloppez un délégué autour de votre méthode, obtenez le MethodInfo, et vous êtes prêt à aller. Voici un exemple:
private void FuncPoo() { } ... // Get the name of the function ssortingng funcName = new Action(FuncPoo).Method.Name;
Malheureusement, cela ne fonctionne que pour les méthodes; il ne fonctionne pas pour les propriétés, car vous ne pouvez pas avoir de delegates pour les méthodes getter ou setter de propriété. (Cela semble être une limitation stupide, OMI.)
La solution consiste à utiliser une arborescence d’expression et à séparer cette arborescence d’expression pour trouver le MemberInfo
correspondant. Il y a un peu plus de détails et de commentaires dans cette note (bien que ce ne soit pas le code pour retirer le membre – c’est dans une autre question SO quelque part, je crois).
Malheureusement, comme les arbres d’expression n’existent pas dans .NET 2.0, il n’y a vraiment pas d’équivalent.
Une solution pour éviter les fautes de frappe consiste à disposer d’un ensemble d’accesseurs qui récupèrent le PropertyInfo
correspondant à une propriété particulière et à les tester. Ce serait le seul endroit qui contenait la ficelle. Cela éviterait la duplication et faciliterait la refactorisation, mais c’est un peu draconien.
Une extension de ce que fait reshefm, qui simplifie l’utilisation de l’opérateur nameof () et donne également les noms des méthodes et des membres de la classe et des méthodes:
/// /// Provides the extension method that works as a workarounds for a nameof() operator, /// which should be added to C# sometime in the future. /// public static class NameOfHelper { /// /// Returns a ssortingng represantaion of a property name (or a method name), which is given using a lambda expression. /// /// The type of the parameter. /// The type of the property (or the method's return type), which is used in the parameter. /// An object, that has the property (or method), which its name is returned. /// A Lambda expression of this pattern: x => x.Property
/// Where the x is the and the Property is the property symbol of x.
/// (For a method, use: x => x.Method() /// A ssortingng that has the name of the given property (or method). public static ssortingng nameof(this T obj, Expression> expression) { MemberExpression memberExp = expression.Body as MemberExpression; if (memberExp != null) return memberExp.Member.Name; MethodCallExpression methodExp = expression.Body as MethodCallExpression; if (methodExp != null) return methodExp.Method.Name; throw new ArgumentException("'expression' should be a member expression or a method call expression.", "expression"); } /// /// Returns a ssortingng represantaion of a property name (or a method name), which is given using a lambda expression. /// /// The type of the property (or the method's return type), which is used in the parameter. /// A Lambda expression of this pattern: () => x.Property
/// Where Property is the property symbol of x.
/// (For a method, use: () => x.Method() /// A ssortingng that has the name of the given property (or method). public static ssortingng nameof(Expression> expression) { MemberExpression memberExp = expression.Body as MemberExpression; if (memberExp != null) return memberExp.Member.Name; MethodCallExpression methodExp = expression.Body as MethodCallExpression; if (methodExp != null) return methodExp.Method.Name; throw new ArgumentException("'expression' should be a member expression or a method call expression.", "expression"); } }
Pour l’utiliser:
static class Program { static void Main() { ssortingng strObj = null; Console.WriteLine(strObj.nameof(x => x.Length)); //gets the name of an object's property. Console.WriteLine(strObj.nameof(x => x.GetType())); //gets the name of an object's method. Console.WriteLine(NameOfHelper.nameof(() => ssortingng.Empty)); //gets the name of a class' property. Console.WriteLine(NameOfHelper.nameof(() => ssortingng.Copy(""))); //gets the name of a class' method. } }
À moins que quelqu’un change d’avis, le nameof
opérateur semble venir en C # 6. Voici les notes de la réunion de conception à ce sujet:
La solution acceptée est sympa, simple et élégante.
Cependant, la construction d’un arbre d’expression est coûteuse et j’ai besoin du chemin complet de la propriété.
J’ai donc changé un peu. Ce n’est pas du tout élégant, mais c’est simple et fonctionne bien dans la plupart des cas:
public static ssortingng Property(Expression> expression) { var s = expression.Body.ToSsortingng(); var p = s.Remove(0, s.IndexOf('.') + 1); return p; }
Exemple:
? Nameof.Property(c => c.Style.BackColor.A); "Style.BackColor.A"
Cela fait partie de la langue dans C # 6.0
La réponse de reshefm est plutôt bonne, mais cette API est un peu plus simple:
Exemple d’utilisation: NameOf.Property(() => new Order().Status)
using System; using System.Diagnostics.Contracts; using System.Linq.Expressions; namespace AgileDesign.Utilities { public static class NameOf { /// /// Returns name of any method expression with any number of parameters either void or with a return value /// /// /// Any method expression with any number of parameters either void or with a return value /// /// /// Name of any method with any number of parameters either void or with a return value /// [Pure] public static ssortingng Method(Expression expression) { Contract.Requires(expression != null); return ( (MethodCallExpression)expression.Body ).Method.Name; } /// /// Returns name of property, field or parameter expression (of anything but method) /// /// /// Property, field or parameter expression /// /// /// Name of property, field, parameter /// [Pure] public static ssortingng Member(Expression> expression) { Contract.Requires(expression != null); if(expression.Body is UnaryExpression) { return ((MemberExpression)((UnaryExpression)expression.Body).Operand).Member.Name; } return ((MemberExpression)expression.Body).Member.Name; } } }
Le code complet est ici: http://agiledesignutilities.codeplex.com/SourceControl/changeset/view/b76cefa4234a#GeneralPurpose/NameOf.cs