トップ回答者
インターフェイスに関連付けた属性

質問
-
お世話になっております。
[AttributeUsage(System.AttributeTargets.All, Inherited = true)]
class Atr1 : System.Attribute { }
[Atr1]class BaseClass { }
[Atr1]interface IBaseClass { }
class DerivedClass : BaseClass { } ①
class DerivedClass : IBaseClass { } ②
上記のDerivedClassクラスの属性値を下記のプログラムで取得しようとしていますが、
①では
Attributes on Derived Class: ConsoleApplication1.Atr1
②では、
Attributes on Derived Class: (なし)
となり、インターフェイスに付与した属性が取得できません。
継承されているのかどうか確認したいのですが、どのようにすると取得できますか。
教えてください。public class TestAttributeUsage
{
static void Main()
{
DerivedClass d = new DerivedClass();
Console.WriteLine("Attributes on Derived Class:");
Object[] attrs = d.GetType().GetCustomAttributes(true);
foreach (Attribute attr in attrs)
{
Console.WriteLine(attr);
}
}
}
}
回答
-
インターフェースの属性は、タイプ ツリーからは手に入らないと思います。
実装しているインターフェースの属性も検索したいならば、GetInterfaces() 等で実装インターフェースを列挙して、そのすべてのタイプ ツリーを検索する必要があるかと。
IEnumerable<T> GetAttributesWithImplementedInterfaces<T>(Type t) where T : Attribute
{
foreach (var a in t.GetAttributes(typeof(T), true)) yield return (T) a;
foreach (var a in t.GetInterfaces().Select(GetAttributesWithImplementedInterfaces<T>).SelectMany(i => i)) yield return (T) a;
}
foreach (var a in GetAttributesWithImplementedInterfaces(d.GetType()))
Console.WriteLine(a);ためしてませんが、こんなかんじ。
すべての返信
-
インターフェースの属性は、タイプ ツリーからは手に入らないと思います。
実装しているインターフェースの属性も検索したいならば、GetInterfaces() 等で実装インターフェースを列挙して、そのすべてのタイプ ツリーを検索する必要があるかと。
IEnumerable<T> GetAttributesWithImplementedInterfaces<T>(Type t) where T : Attribute
{
foreach (var a in t.GetAttributes(typeof(T), true)) yield return (T) a;
foreach (var a in t.GetInterfaces().Select(GetAttributesWithImplementedInterfaces<T>).SelectMany(i => i)) yield return (T) a;
}
foreach (var a in GetAttributesWithImplementedInterfaces(d.GetType()))
Console.WriteLine(a);ためしてませんが、こんなかんじ。
-
ご返事ありがとうございます。
この質問をする経緯ですが、ただいまWCF勉強中で、サービスコントラクト属性をインターフェイスに、そして実装をクラスにすることが推奨みたいな解説があり、
ただ、ServiceContractAttributeクラスを確認したところ、Inheritedの値がfalseであったため、派生したクラスにはつかないのに大丈夫なん、
本当かなと疑問をもち、上記サンプルプログラムを 使用して確認したところ、Inheritedの値がtrueであろうが、falseであろうが、属性が継承されていないので、
質問にいたりました。佐祐理氏の、説明で理解できました。
>インターフェースは「実装」であって、継承・オーバーライドではないからです。
p.s.
WCFでの疑問の方は、おそらくインターフェイスにサービスコントラクト属性を付ける理由は、WSDL,XDLなどのメタファイル用か送信側の定義の用で
実際メッセージを受信したときには、クラスのインスタンスを生成するメカニズムが別にあると推測し学習を進めたいと思います。