我有一個聲明爲Internal的類。它裝飾着各種註釋。特別是[DisplayName(「我的顯示名稱」)]註釋。我有一些代碼將檢索的價值,但只有在該類聲明爲公共的時纔有效。我對使用反射有點新鮮。我相信我需要指定BindingFlags.NonPublic被使用,但我不知道在哪裏。從內部類獲取DisplayNameAttribute
LinqPAD代碼:
void Main()
{
List<SpGetProfileInfoResult> p = new List<SpGetProfileInfoResult>();
p.Add(new SpGetProfileInfoResult() { FName = "Eric" });
p.Add(new SpGetProfileInfoResult() { FName = "Mike" });
p.Dump();
foreach (var item in p)
{
Console.WriteLine(item.DisplayName(i => i.FName));
Console.WriteLine(item.FName);
}
}
public partial class SpGetProfileInfoResult
{
// Uncomment this annotation to see that this part will work
// [System.ComponentModel.DisplayNameAttribute("[BILLTO-FNAME]")]
public string FName { get; set; }
}
public partial class SpGetProfileInfoResult
{
internal class Metadata
{
// This attribute is never available seems.
[System.ComponentModel.DisplayNameAttribute("[BILL-FNAME]")]
public string FName { get; set; }
}
}
public static class Tag
{
public static T GetAttribute<T>(this MemberInfo member, bool isRequired) where T : Attribute
{
var attribute = member.GetCustomAttributes(typeof(T), false).SingleOrDefault();
if (attribute == null && isRequired)
{
throw new ArgumentException(
string.Format(
"The {0} attribute must be defined on member {1}",
typeof(T).Name,
member.Name));
}
return (T)attribute;
}
public static string DisplayName<T>(this T src,Expression<Func<T, object>> propertyExpression)
{
Type metadata = null;
var memberInfo = GetPropertyInformation(propertyExpression.Body);
if (memberInfo == null)
{
throw new ArgumentException(
"No property reference expression was found.",
"propertyExpression");
}
var attr = memberInfo.GetAttribute<DisplayNameAttribute>(false);
if (attr == null)
{
return memberInfo.Name;
}
return attr.DisplayName;
}
public static MemberInfo GetPropertyInformation(Expression propertyExpression)
{
MemberExpression memberExpr = propertyExpression as MemberExpression;
if (memberExpr == null)
{
UnaryExpression unaryExpr = propertyExpression as UnaryExpression;
if (unaryExpr != null && unaryExpr.NodeType == ExpressionType.Convert)
{
memberExpr = unaryExpr.Operand as MemberExpression;
}
}
if (memberExpr != null && memberExpr.Member.MemberType == MemberTypes.Property)
{
return memberExpr.Member;
}
return null;
}
}
用法:
如果你沒有LinqPAD,你應該只創建一個新的C#程序下載它,那麼你可以測試這個很容易地在LinkPAD
Debug.WriteLine(item.DisplayName(i => i.FName));
工程,當我嘗試它。當你嘗試時出了什麼問題?另外,你已經包含了代碼是很好的,但是最小的*編譯*例子真的有幫助。 – AakashM 2012-01-09 13:56:43
有兩個部分類,一個具有許多屬性,它是生成的類,然後是上面的類,它是元數據類。我只能得到生成的類的屬性,而沒有任何內部類。該項目非常龐大,所以我無法創建這樣一個小例子。我試圖將其烘焙到最基本的組件上。 – ewahner 2012-01-09 14:58:30
是的,我知道這很棘手。但是鑑於'internal'和'public'之間的行爲有所不同,我們確實需要知道* assembly *分界線在哪裏。按照現狀,唯一的* reflection *調用是'GetCustomAttributes',並且沒有任何'BindingFlags'參數。 – AakashM 2012-01-09 15:31:45