如何从C#中的对象实例获取自定义属性

假设我有一个名为Test的类,其中一个名为Title的属性具有自定义属性:

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

还有一个名为DbField的扩展方法。 我想知道是否可以在c#中从对象实例获取自定义属性。

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

可以这样做吗?

这是一种方法。 扩展方法有效,但不是那么容易。 我创建一个表达式,然后检索自定义属性。

 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(this T obj, Expression> 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; } } } 
 namespace ConsoleApplication2 { class Program { static void Main(string[] args) { Test t = new Test(); Console.WriteLine(t.FieldName("Title").FieldName()); Console.WriteLine(t.FieldName("Title").FieldIsPrimaryKey()); } } 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(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(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; } } } 

它是,但最终它将是一种迂回的方式,因为你将在你的实例上调用GetType来获取Type实例,然后对它进行处理(通常是这样)。

在这种特定情况下,您的扩展方法无法获取属性信息,因为您传递给它的所有内容都是字符串。

最终,您需要的是获取PropertyInfo 。 其他答案是指Type ,它们缺少的是,这不是获取所需PropertyInfo的属性信息的唯一方法。

您可以通过传递带有字符串的Type实例(可能是属性名称)来实现,因此您可以在Type上调用GetProperty

另一种方法是这样做,因为C#3.0的方法是采用Expression ,然后使用Expression的部分来获取PropertyInfo 。 在这种情况下,您将采用Expression>TResult为字符串的内容。

获得PropertyInfo ,可以在其上调用GetCustomAttributes ,并查找属性。

表达式方法的优点是Expression派生自LambdaExpression ,您可以调用Compile on,然后调用以获取实际值(如果需要)。

正如已经指出的那样,原始海报所描述的语法是不可能的,因为你无法在扩展方法中获得对PropertyInfo的引用。 这样的事情怎么样:

 // 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"; } 

然后,您可以像下面这样获取信息:

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

不,这是不可能的。 这样做的原因是它是值,而不是属性本身将被发送到任何可以获取此信息的自定义扩展方法。 一旦进入该扩展方法,就没有可靠的方法来追溯到属性本身。

对于枚举值可能是有可能的 ,但就POCO的属性而言,它不会起作用。

要获取属性值,您需要属性适用的类型。 您的扩展方法只获取字符串值(Title的值),因此您将无法获取字符串来自的实际实例,因此您无法获得Title属性所属的原始类型。 这将使您无法从扩展方法中获取属性值。