[英]How to get a custom attribute from object instance in 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<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; }
}
}
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;
}
}
}
是的,但是最终这将是一种回旋的方式,因为您将通过在公开该属性的实例上调用GetType
来获取Type
实例,然后对其进行处理(通常不这样做)。
在这种情况下,您的扩展方法将无法获取属性信息,因为您要传递给它的只是一个字符串。
最终,您需要从中获取PropertyInfo
东西。 其他答案都指向Type
,它们缺少的是,这不是在想要的PropertyInfo
处获取属性信息的唯一方法。
您可以通过向Type
实例传递一个大概带有属性名称的字符串来实现,因此您可以在Type
上调用GetProperty
。
自C#3.0起,执行此操作的另一种方法是拥有一个使用Expression<T>
,然后使用Expression
的各个部分来获取PropertyInfo
。 在这种情况下,您将使用Expression<Func<string>>
或TResult
为string的内容。
一旦有了PropertyInfo
,就可以在其上调用GetCustomAttributes
并查找您的属性。
表达式方法的优点是Expression<T>
源自LambdaExpression
,您可以对其调用Compile
,然后在需要时调用以获得实际值。
正如已经指出的那样,使用原始发布者描述的语法是不可能的,因为您无法在扩展方法内获得对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");
为了获得属性值,您需要属性适用的类型。 您的扩展方法仅获得一个字符串值(Title的值),因此您将无法获取该字符串来自的实际实例,因此也无法获得Title属性所属的原始类型。 这将使得无法从扩展方法中获取属性值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.