¿Hay una solución para la falta del operador ‘nameof’ en C # para el enlace de datos seguro?

Ha habido mucho sentimiento para incluir un nameof operador en C #. Como ejemplo de cómo funcionaría este operador, nameof(Customer.Name) devolvería la cadena "Name" .

Tengo un objeto de dominio. Y tengo que atarlo. Y necesito nombres de propiedades como cadenas entonces. Y quiero que sean seguros de tipo.

Recuerdo encontrar una solución en .NET 3.5 que proporcionaba la funcionalidad de nameof y expresiones lambda involucradas. Sin embargo, no he podido encontrar esta solución. ¿Alguien puede proporcionarme esa solución?

También estoy interesado en una forma de implementar la funcionalidad de nameof en .NET 2.0 si eso es posible.

Este código básicamente hace eso:

 class Program { static void Main() { var propName = Nameof.Property(e => e.Name); Console.WriteLine(propName); } } public class Nameof { public static string 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; } } 

(Por supuesto, es código 3.5 …)

Mientras que reshefm y Jon Skeet muestran la forma correcta de hacer esto usando expresiones, vale la pena señalar que hay una forma más económica de hacer esto para los nombres de métodos:

Envuelva a un delegado en su método, obtenga MethodInfo y estará listo. Aquí hay un ejemplo:

 private void FuncPoo() { } ... // Get the name of the function string funcName = new Action(FuncPoo).Method.Name; 

Lamentablemente, esto solo funciona por métodos; no funciona para las propiedades, ya que no puede tener delegates en los métodos getter o setter de la propiedad. (Parece una limitación tonta, IMO.)

La solución consiste en utilizar un árbol de expresiones y separar ese árbol de expresiones para encontrar el MemberInfo relevante. Hay un poco más de detalles y comentarios en esta nota (aunque no el código para sacar al miembro, eso está en otra pregunta de SO en algún lado, creo).

Desafortunadamente, como los árboles de expresión no existen en .NET 2.0, realmente no hay equivalente.

Una solución para evitar errores tipográficos es tener un conjunto de accesadores que capturen el PropertyInfo relevante para una propiedad en particular, y que la unidad los pruebe. Ese sería el único lugar que tenía la cuerda. Esto evitaría la duplicación y facilitaría la refactorización, pero es un poco draconiano.

Una extensión de lo que hizo Reshefm, que simplificó el uso del operador name of () y también proporciona los nombres de los métodos y miembros y métodos de la clase:

 ///  /// 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 string 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 string that has the name of the given property (or method). public static string 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 string 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 string that has the name of the given property (or method). public static string 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"); } }

Para usarlo:

 static class Program { static void Main() { string 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(() => string.Empty)); //gets the name of a class' property. Console.WriteLine(NameOfHelper.nameof(() => string.Copy(""))); //gets the name of a class' method. } } 

A menos que alguien cambie de parecer, el nameof operador parece estar en C # 6. Estas son las notas de la reunión de diseño al respecto:

https://roslyn.codeplex.com/discussions/552376

https://roslyn.codeplex.com/discussions/552377

La solución aceptada es agradable, simple y elegante.

Sin embargo, construir un árbol de expresiones es costoso, y necesito toda la ruta de la propiedad.

Así que lo cambié un poco. No es nada elegante, pero es simple y funciona bien en la mayoría de los casos:

 public static string Property(Expression> expression) { var s = expression.Body.ToString(); var p = s.Remove(0, s.IndexOf('.') + 1); return p; } 

Ejemplo:

 ? Nameof.Property(c => c.Style.BackColor.A); "Style.BackColor.A" 

Esto es parte del lenguaje en C # 6.0

https://msdn.microsoft.com/en-us/magazine/dn802602.aspx

La respuesta de reshefm es bastante buena, pero esto es un poco más simple API IMO:

Ejemplo de uso: 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 string 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 string 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; } } } 

El código completo está aquí: http://agiledesignutilities.codeplex.com/SourceControl/changeset/view/b76cefa4234a#GeneralPurpose/NameOf.cs