我有一个声明为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