内部に宣言されているクラスがあります。さまざまな注釈で装飾されています。特に、[DisplayName( "My Display Name")]アノテーションがあります。私は値を取得するいくつかのコードを持っていますが、クラスがpublic宣言されている場合にのみ動作します。私はリフレクションを使うのは初めてのことです。私は、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#プログラムを作成することによって、かなり簡単に、あなたはこれをテストすることができ、それをダウンロードしてくださいin LinkPAD
Debug.WriteLine(item.DisplayName(i => i.FName));
私が試したときに動作します。あなたがそれを試して何がうまくいかない?また、コードをインクルードしたのは良いことですが、最小限のコンパイル*の例が役立ちます。 – AakashM
2つの部分クラスがあります。1つは多くの属性を持ち、1つは生成されたクラスで、もう1つはメタデータクラスです。私は、生成されたクラスの属性と内部クラスの属性には到達できません。このプロジェクトは巨大なものなので、私はそのような小さな例を作ることができませんでした。私はそれを最も基本的なコンポーネントに焼き付けようとしました。 – ewahner
ええ、それは私が知っているトリッキーです。しかし、「内部」と「公的」の間に行動の違いがあることを考えると、*アセンブリ*分割線がどこにあるかを本当に知る必要があります。物事が立てば、あなたが作っている唯一の* reflection *呼び出しは 'GetCustomAttributes'であり、' BindingFlags'パラメータはありません。 – AakashM