una que objetos metodos llamar instancia herencia ejemplos dinamicos clases clase atributos c# .net reflection custom-attributes

que - objetos dinamicos c#



Cómo obtener un atributo personalizado de la instancia del objeto en C# (6)

Digamos que tengo una clase llamada Prueba con una propiedad llamada Título con un atributo personalizado:

public class Test { [DatabaseField("title")] public string Title { get; set; } }

Y un método de extensión llamado DbField. Me pregunto si incluso es posible obtener un atributo personalizado de una instancia de objeto en c #.

Test t = new Test(); string fieldName = t.Title.DbField(); //fieldName will equal "title", the same name passed into the attribute above

Se puede hacer esto?


Aquí hay un enfoque. El método de extensión funciona, pero no es tan fácil. Creo una expresión y luego recupero el atributo personalizado.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace ConsoleApplication1 { public class DatabaseFieldAttribute : Attribute { public string Name { get; set; } public DatabaseFieldAttribute(string name) { this.Name = name; } } public static class MyClassExtensions { public static string DbField<T>(this T obj, Expression<Func<T, string>> value) { var memberExpression = value.Body as MemberExpression; var attr = memberExpression.Member.GetCustomAttributes(typeof(DatabaseFieldAttribute), true); return ((DatabaseFieldAttribute)attr[0]).Name; } } class Program { static void Main(string[] args) { var p = new Program(); Console.WriteLine("DbField = ''{0}''", p.DbField(v => v.Title)); } [DatabaseField("title")] public string Title { get; set; } } }


Como se ha señalado, no es posible con la sintaxis descrita en el póster original, porque no se puede obtener una referencia a PropertyInfo dentro del método de extensión. ¿Qué tal algo así?

// Extension method public static string GetDbField(this object obj, string propertyName) { PropertyInfo prop = obj.GetType().GetProperty(propertyName); object[] dbFieldAtts = prop.GetCustomAttributes(typeof(DatabaseFieldAttribute), true); if (dbFieldAtts != null && dbFieldAtts.Length > 0) { return ((DatabaseFieldAttribute)dbFieldAtts[0]).Name; } return "UNDEFINED"; }

A continuación, puede obtener la información de la siguiente manera:

Test t = new Test(); string dbField = t.GetDbField("Title");


Lo es, pero en última instancia va a ser una forma indirecta, ya que hará que la instancia de Type GetType a GetType en su instancia que expone la propiedad, y luego trabaje en eso (la mayoría de las veces).

En este caso específico, su método de extensión no podrá obtener la información del atributo porque todo lo que le está pasando es una cadena.

En última instancia, lo que necesita es algo para obtener PropertyInfo para la propiedad. Otras respuestas se refieren al Type , lo que les falta es que esta no es la única forma de obtener la información de atributo en el PropertyInfo que desea.

Puede hacerlo pasando una instancia de Type con una cadena, presumiblemente, con el nombre de la propiedad, para que pueda llamar a GetProperty en el Type .

Otra forma de hacerlo desde C # 3.0 ha sido tener un método que toma una Expression<T> y luego usar las partes de la Expression para obtener PropertyInfo . En este caso, tomaría una Expression<Func<string>> o algo donde TResult es una cadena.

Una vez que tenga PropertyInfo , puede llamar a GetCustomAttributes y buscar su atributo.

La ventaja del enfoque de expresión es que Expression<T> deriva de LambdaExpression , que puede llamar a Compile on, y luego llama para obtener el valor real, si lo necesita.


No, no es posible. La razón de esto es que es el valor, y no la propiedad en sí, lo que se enviará a cualquier método de extensión personalizado que obtenga esta información. Una vez que ingresa en ese método de extensión, no hay una forma confiable de rastrear la propiedad.

Es posible que los valores enum , pero en cuanto a las propiedades en POCO, no va a funcionar.


Para obtener el valor del atributo, necesita el tipo al que se aplica el atributo. Su método de extensión solo obtiene un valor de cadena (el valor de Título), por lo que no podría obtener la instancia real de la que proviene la cadena, y por lo tanto no puede obtener el tipo original al que pertenece la propiedad Título. Esto hará que sea imposible obtener el valor del atributo de su método de extensión.


namespace ConsoleApplication2 { class Program { static void Main(string[] args) { Test t = new Test(); Console.WriteLine(t.FieldName("Title").FieldName<DatabaseFieldAttribute>()); Console.WriteLine(t.FieldName("Title").FieldIsPrimaryKey<DatabaseFieldAttribute>()); } } public class Test { [DatabaseField("titlezzz", true)] public string Title { get; set; } } public class BaseDatabaseFieldAttribute : Attribute { private readonly string _name; public string Name { get { return _name; } } public BaseDatabaseFieldAttribute(string name) { _name = name; } } public class DatabaseFieldAttribute : BaseDatabaseFieldAttribute { private readonly bool _isPrimaryKey; public bool IsPrimaryKey { get { return _isPrimaryKey; } } public DatabaseFieldAttribute(string name, bool isPrimaryKey): base(name) { _isPrimaryKey = isPrimaryKey; } } public static class Helper { public static PropertyInfo FieldName(this object obj, string propertyName) { return obj.GetType().GetProperty(propertyName); } public static string FieldName<T>(this PropertyInfo property) where T: BaseDatabaseFieldAttribute { object[] os = property.GetCustomAttributes(typeof(T), false); if (os != null && os.Length >= 1) return (os[0] as T).Name; else return "N/A"; } public static bool? FieldIsPrimaryKey<T>(this PropertyInfo property) where T : DatabaseFieldAttribute { object[] os = property.GetCustomAttributes(typeof(T), false); if (os != null && os.Length >= 1) return (os[0] as T).IsPrimaryKey; else return null; } } }