visual tag obtener nombre archivo c# reflection properties

tag - obtener nombre del archivo openfiledialog c#



Obtener el nombre de la propiedad como una cadena (13)

Basado en la respuesta que ya está en la pregunta y en este artículo: https://handcraftsman.wordpress.com/2008/11/11/how-to-get-c-property-names-without-magic-strings/ I estoy presentando mi solución a este problema:

public static class PropertyNameHelper { /// <summary> /// A static method to get the Propertyname String of a Property /// It eliminates the need for "Magic Strings" and assures type safety when renaming properties. /// See: http://stackoverflow.com/questions/2820660/get-name-of-property-as-a-string /// </summary> /// <example> /// // Static Property /// string name = PropertyNameHelper.GetPropertyName(() => SomeClass.SomeProperty); /// // Instance Property /// string name = PropertyNameHelper.GetPropertyName(() => someObject.SomeProperty); /// </example> /// <typeparam name="T"></typeparam> /// <param name="propertyLambda"></param> /// <returns></returns> public static string GetPropertyName<T>(Expression<Func<T>> propertyLambda) { var me = propertyLambda.Body as MemberExpression; if (me == null) { throw new ArgumentException("You must pass a lambda of the form: ''() => Class.Property'' or ''() => object.Property''"); } return me.Member.Name; } /// <summary> /// Another way to get Instance Property names as strings. /// With this method you don''t need to create a instance first. /// See the example. /// See: https://handcraftsman.wordpress.com/2008/11/11/how-to-get-c-property-names-without-magic-strings/ /// </summary> /// <example> /// string name = PropertyNameHelper((Firma f) => f.Firmenumsatz_Waehrung); /// </example> /// <typeparam name="T"></typeparam> /// <typeparam name="TReturn"></typeparam> /// <param name="expression"></param> /// <returns></returns> public static string GetPropertyName<T, TReturn>(Expression<Func<T, TReturn>> expression) { MemberExpression body = (MemberExpression)expression.Body; return body.Member.Name; } }

Y una prueba que también muestra el uso, por ejemplo, y propiedades estáticas:

[TestClass] public class PropertyNameHelperTest { private class TestClass { public static string StaticString { get; set; } public string InstanceString { get; set; } } [TestMethod] public void TestGetPropertyName() { Assert.AreEqual("StaticString", PropertyNameHelper.GetPropertyName(() => TestClass.StaticString)); Assert.AreEqual("InstanceString", PropertyNameHelper.GetPropertyName((TestClass t) => t.InstanceString)); } }

(Vea a continuación la solución que creé usando la respuesta que acepté)

Estoy tratando de mejorar el mantenimiento de algunos códigos que implican reflexión. La aplicación tiene una interfaz .NET Remoting que expone (entre otras cosas) un método llamado Execute para acceder a partes de la aplicación no incluidas en su interfaz remota publicada.

Así es como la aplicación designa las propiedades (una estática en este ejemplo) a las que se debe acceder mediante Execute:

RemoteMgr.ExposeProperty("SomeSecret", typeof(SomeClass), "SomeProperty");

Entonces un usuario remoto podría llamar:

string response = remoteObject.Execute("SomeSecret");

y la aplicación usaría la reflexión para encontrar SomeClass.SomeProperty y devolver su valor como una cadena.

Desafortunadamente, si alguien renombra SomeProperty y se olvida de cambiar el tercer parm de ExposeProperty (), rompe este mecanismo.

Necesito el equivalente de:

SomeClass.SomeProperty.GetTheNameOfThisPropertyAsAString()

para usar como el 3er parm en ExposeProperty, por lo que las herramientas de refactorización se encargarían de cambiar el nombre.

¿Hay alguna forma de hacer esto? Gracias por adelantado.

De acuerdo, esto es lo que terminé creando (basado en la respuesta que seleccioné y la pregunta a la que hizo referencia):

// <summary> // Get the name of a static or instance property from a property access lambda. // </summary> // <typeparam name="T">Type of the property</typeparam> // <param name="propertyLambda">lambda expression of the form: ''() => Class.Property'' or ''() => object.Property''</param> // <returns>The name of the property</returns> public string GetPropertyName<T>(Expression<Func<T>> propertyLambda) { var me = propertyLambda.Body as MemberExpression; if (me == null) { throw new ArgumentException("You must pass a lambda of the form: ''() => Class.Property'' or ''() => object.Property''"); } return me.Member.Name; }

Uso:

// Static Property string name = GetPropertyName(() => SomeClass.SomeProperty); // Instance Property string name = GetPropertyName(() => someObject.SomeProperty);

Ahora con esta genial capacidad, es hora de simplificar el método ExposeProperty. Pulir los picaportes es un trabajo peligroso ...

Gracias a todos.


Con C # 6.0, esto ya no es un problema, como puede hacer:

nameof(SomeProperty)

Esta expresión se resuelve en tiempo de compilación en "SomeProperty" .

Documentación de MSDN de nameof .


De acuerdo, esto es lo que terminé creando (basado en la respuesta que seleccioné y la pregunta a la que hizo referencia):

// <summary> // Get the name of a static or instance property from a property access lambda. // </summary> // <typeparam name="T">Type of the property</typeparam> // <param name="propertyLambda">lambda expression of the form: ''() => Class.Property'' or ''() => object.Property''</param> // <returns>The name of the property</returns> public string GetPropertyName<T>(Expression<Func<T>> propertyLambda) { var me = propertyLambda.Body as MemberExpression; if (me == null) { throw new ArgumentException("You must pass a lambda of the form: ''() => Class.Property'' or ''() => object.Property''"); } return me.Member.Name; }

Uso:

// Static Property string name = GetPropertyName(() => SomeClass.SomeProperty); // Instance Property string name = GetPropertyName(() => someObject.SomeProperty);


Hay un truco bien conocido para extraerlo de la expresión lambda (esto es de la clase PropertyObserver, por Josh Smith, en su base MVVM):

private static string GetPropertyName<TPropertySource> (Expression<Func<TPropertySource, object>> expression) { var lambda = expression as LambdaExpression; MemberExpression memberExpression; if (lambda.Body is UnaryExpression) { var unaryExpression = lambda.Body as UnaryExpression; memberExpression = unaryExpression.Operand as MemberExpression; } else { memberExpression = lambda.Body as MemberExpression; } Debug.Assert(memberExpression != null, "Please provide a lambda expression like ''n => n.PropertyName''"); if (memberExpression != null) { var propertyInfo = memberExpression.Member as PropertyInfo; return propertyInfo.Name; } return null; }

Lo siento, esto faltaba algo de contexto. Esto fue parte de una clase más grande donde TPropertySource es la clase que contiene la propiedad. Puede hacer que la función sea genérica en TPropertySource para extraerla de la clase. Recomiendo echar un vistazo al código completo de MVVM Foundation .


He estado usando esta respuesta con gran efecto: Obtenga la propiedad, como una cadena, de una expresión <Func <TModel, TProperty >>

Me doy cuenta de que ya contesté esta pregunta hace un tiempo. La única ventaja que tiene mi otra respuesta es que funciona para propiedades estáticas. Encuentro que la sintaxis en esta respuesta es mucho más útil porque no tiene que crear una variable del tipo que desea reflejar.


La clase PropertyInfo debería ayudarte a lograr esto, si entiendo correctamente.

  1. Método Type.GetProperties ()

    PropertyInfo[] propInfos = typeof(ReflectedType).GetProperties(); propInfos.ToList().ForEach(p => Console.WriteLine(string.Format("Property name: {0}", p.Name));

¿Esto es lo que necesitas?


Modifiqué tu solución para encadenar varias propiedades:

public static string GetPropertyName<T>(Expression<Func<T>> propertyLambda) { MemberExpression me = propertyLambda.Body as MemberExpression; if (me == null) { throw new ArgumentException("You must pass a lambda of the form: ''() => Class.Property'' or ''() => object.Property''"); } string result = string.Empty; do { result = me.Member.Name + "." + result; me = me.Expression as MemberExpression; } while (me != null); result = result.Remove(result.Length - 1); // remove the trailing "." return result; }

Uso:

string name = GetPropertyName(() => someObject.SomeProperty.SomeOtherProperty); // returns "SomeProperty.SomeOtherProperty"


Pregunta anterior, pero otra respuesta a esta pregunta es crear una función estática en una clase auxiliar que usa CallerMemberNameAttribute.

public static string GetPropertyName([CallerMemberName] String propertyName = null) { return propertyName; }

Y luego úsalo como:

public string MyProperty { get { Console.WriteLine("{0} was called", GetPropertyName()); return _myProperty; } }


Puede usar Reflection para obtener los nombres reales de las propiedades.

http://www.csharp-examples.net/reflection-property-names/

Si necesita una forma de asignar un "Nombre de cadena" a una propiedad, ¿por qué no escribe un atributo que puede reflejar para obtener el nombre de la cadena?

[StringName("MyStringName")] private string MyProperty { get { ... } }



Tuve algunas dificultades para usar las soluciones ya sugeridas para mi caso de uso específico, pero finalmente lo descubrí. No creo que mi caso específico sea digno de una nueva pregunta, entonces estoy publicando mi solución aquí para referencia. (Esto está muy relacionado con la pregunta y proporciona una solución para cualquier persona con un caso similar al mío).

El código con el que terminé se ve así:

public class HideableControl<T>: Control where T: class { private string _propertyName; private PropertyInfo _propertyInfo; public string PropertyName { get { return _propertyName; } set { _propertyName = value; _propertyInfo = typeof(T).GetProperty(value); } } protected override bool GetIsVisible(IRenderContext context) { if (_propertyInfo == null) return false; var model = context.Get<T>(); if (model == null) return false; return (bool)_propertyInfo.GetValue(model, null); } protected void SetIsVisibleProperty(Expression<Func<T, bool>> propertyLambda) { var expression = propertyLambda.Body as MemberExpression; if (expression == null) throw new ArgumentException("You must pass a lambda of the form: ''vm => vm.Property''"); PropertyName = expression.Member.Name; } } public interface ICompanyViewModel { string CompanyName { get; } bool IsVisible { get; } } public class CompanyControl: HideableControl<ICompanyViewModel> { public CompanyControl() { SetIsVisibleProperty(vm => vm.IsVisible); } }

Lo importante para mí es que en la clase CompanyControl , el compilador solo me permitirá elegir una propiedad booleana de ICompanyViewModel lo que facilita que otros desarrolladores puedan hacerlo bien.

La principal diferencia entre mi solución y la respuesta aceptada es que mi clase es genérica y solo quiero hacer coincidir las propiedades del tipo genérico que son booleanas.


Usando GetMemberInfo desde aquí: Recuperando el nombre de la propiedad de la expresión lambda puede hacer algo como esto:

RemoteMgr.ExposeProperty(() => SomeClass.SomeProperty)

public class SomeClass { public static string SomeProperty { get { return "Foo"; } } } public class RemoteMgr { public static void ExposeProperty<T>(Expression<Func<T>> property) { var expression = GetMemberInfo(property); string path = string.Concat(expression.Member.DeclaringType.FullName, ".", expression.Member.Name); // Do ExposeProperty work here... } } public class Program { public static void Main() { RemoteMgr.ExposeProperty("SomeSecret", () => SomeClass.SomeProperty); } }


es cómo lo implementé, la razón detrás es si la clase de la que desea obtener el nombre de su miembro no es estática, entonces necesita crear una instancia de eso y luego obtener el nombre del miembro. tan genérico aquí viene a ayudar

public static string GetName<TClass>(Expression<Func<TClass, object>> exp) { MemberExpression body = exp.Body as MemberExpression; if (body == null) { UnaryExpression ubody = (UnaryExpression)exp.Body; body = ubody.Operand as MemberExpression; } return body.Member.Name; }

el uso es así

var label = ClassExtension.GetName<SomeClass>(x => x.Label); //x is refering to ''SomeClass''