如何从C#中的对象实例获取自定义属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2329738/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get a custom attribute from object instance in C#
提问by kabucey
Let's say I have a class called Test with one property called Title with a custom attribute:
假设我有一个名为 Test 的类,其中一个名为 Title 的属性具有自定义属性:
public class Test
{
[DatabaseField("title")]
public string Title { get; set; }
}
And an extension method called DbField. I am wondering if getting a custom attribute from an object instance is even possible in c#.
还有一个叫做 DbField 的扩展方法。我想知道在 c# 中是否甚至可以从对象实例获取自定义属性。
Test t = new Test();
string fieldName = t.Title.DbField();
//fieldName will equal "title", the same name passed into the attribute above
Can this be done?
这能做到吗?
采纳答案by Nick Randell
Here is an approach. The extension method works, but it's not quite as easy. I create an expression and then retrieve the custom attribute.
这是一个方法。扩展方法有效,但并不那么容易。我创建一个表达式,然后检索自定义属性。
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; }
}
}
回答by casperOne
It is, but ultimately it's going to be a roundabout way, since you will get the Type
instance from calling GetType
on your instance that exposes the property, and then work on that(more often than not).
确实如此,但最终这将是一种迂回的方式,因为您将Type
通过调用GetType
公开属性的实例来获取实例,然后对其进行处理(通常情况下)。
In this specific case, your extension method isn't going to be able to get the attribute information because all you are passing to it is a string.
在这种特定情况下,您的扩展方法将无法获取属性信息,因为您传递给它的只是一个字符串。
Ultimately, what you need is something to get the PropertyInfo
for the property from. Other answers are referring to the Type
, what they lack is, this is not the only way to get the attribute information at the PropertyInfo
which you want.
最终,您需要的是从中获取PropertyInfo
财产的东西。其他答案指的是Type
,他们缺乏的是,这不是获取所需属性信息的唯一方法PropertyInfo
。
You can do that by passing a Type
instance with a string, presumably, with the property name, so you can call GetProperty
on the Type
.
你可以通过传递一个Type
实例与字符串,据推测,与物业的名称,这样你就可以调用GetProperty
的Type
。
Another way of doing this since C# 3.0 has been to have a method that takes an Expression<T>
and then use the parts of the Expression
to get at the PropertyInfo
. In this case, you would take an Expression<Func<string>>
or something where TResult
is string.
自 C# 3.0 以来,另一种方法是Expression<T>
使用一种方法,该方法接受 an然后使用 的部分Expression
来获取PropertyInfo
. 在这种情况下,您将使用字符串Expression<Func<string>>
或TResult
字符串。
Once you have the PropertyInfo
, you can call GetCustomAttributes
on it, and look for your attribute.
一旦你有了PropertyInfo
,你就可以调用GetCustomAttributes
它,并寻找你的属性。
The advantage to the expression approach is that Expression<T>
derives from LambdaExpression
, which you can call Compile
on, and then call to get the actual value, if you need it.
表达式方法的优点是Expression<T>
派生自LambdaExpression
,您可以调用Compile
它,然后在需要时调用以获取实际值。
回答by David Morton
No, it's not possible. The reason for this is that it's the value, and not the property itself that would be sent into any custom extension method that would fetch this information. Once you get into that extension method, there's no reliable way to trace back to the property itself.
不,这不可能。这样做的原因是它是值,而不是属性本身,它会被发送到将获取此信息的任何自定义扩展方法中。一旦进入该扩展方法,就没有可靠的方法可以追溯到属性本身。
It might be possible for enum values, but as far as properties on POCO's, it's not going to work.
回答by NerdFury
In order to get the attribute value, you need the type that the attribute applies to. Your extension method is only getting a string value (the value of Title), so you would not be able to get the actual instance that the string came from, and so you can't get the original type that the Title property belongs to. This will make it impossible to get the attribute value from your extension method.
为了获取属性值,您需要该属性适用的类型。您的扩展方法仅获取一个字符串值(Title 的值),因此您将无法获取该字符串来自的实际实例,因此您无法获取 Title 属性所属的原始类型。这将使您无法从扩展方法中获取属性值。
回答by garik
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;
}
}
}
回答by WayneC
As as been pointed out, it's not possible with the syntax the original poster described, because you can't get a reference to PropertyInfo inside the extension method. What about something like this:
正如所指出的,使用原始海报描述的语法是不可能的,因为您无法在扩展方法中获得对 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";
}
You could then get the info as simply as:
然后,您可以简单地获取信息:
Test t = new Test();
string dbField = t.GetDbField("Title");