2008-10-30 7 views
18

У меня есть интерфейс, который определяет некоторые методы с атрибутами. Эти атрибуты должны быть доступны из вызывающего метода, но метод, который у меня есть, не вытягивает атрибуты из интерфейса. Что мне не хватает?Атрибуты на интерфейсе

public class SomeClass: ISomeInterface 
{ 
    MyAttribute GetAttribute() 
    { 
     StackTrace stackTrace = new StackTrace(); 
     StackFrame stackFrame = stackTrace.GetFrame(1); 
     MethodBase methodBase = stackFrame.GetMethod(); 
     object[] attributes = methodBase.GetCustomAttributes(typeof(MyAttribute), true); 
     if (attributes.Count() == 0) 
      throw new Exception("could not find MyAttribute defined for " + methodBase.Name); 
     return attributes[0] as MyAttribute; 
    } 

    void DoSomething() 
    { 
     MyAttribute ma = GetAttribute(); 
     string s = ma.SomeProperty; 
    } 
} 
+1

Просто проверка, вы установили соответствующий флаг в свой атрибут, чтобы позволить ему наследоваться, не так ли? –

ответ

7

МетодBase будет методом класса, а не интерфейсом. Вам нужно будет искать тот же метод на интерфейсе. В C# это немного проще (поскольку он должен быть как-то именован), но вам нужно будет рассмотреть такие вещи, как явная реализация. Если у вас есть код VB, это будет сложнее, так как метод VB «Foo» может реализовать интерфейс «Бар». Чтобы сделать это, вам нужно будет изучить карту интерфейса:

using System; 
using System.ComponentModel; 
using System.Diagnostics; 
using System.Reflection; 
interface IFoo 
{ 
    void AAA(); // just to push Bar to index 1 
    [Description("abc")] 
    void Bar(); 
} 
class Foo : IFoo 
{ 
    public void AAA() { } // just to satisfy interface 
    static void Main() 
    { 
     IFoo foo = new Foo(); 
     foo.Bar(); 
    } 
    void IFoo.Bar() 
    { 
     GetAttribute(); 
    } 

    void GetAttribute() 
    { // simplified just to obtain the [Description] 

     StackTrace stackTrace = new StackTrace(); 
     StackFrame stackFrame = stackTrace.GetFrame(1); 
     MethodBase classMethod = stackFrame.GetMethod(); 
     InterfaceMapping map = GetType().GetInterfaceMap(typeof(IFoo)); 
     int index = Array.IndexOf(map.TargetMethods, classMethod); 
     MethodBase iMethod = map.InterfaceMethods[index]; 
     string desc = ((DescriptionAttribute)Attribute.GetCustomAttribute(iMethod, typeof(DescriptionAttribute))).Description; 
    } 
} 
+0

Это, похоже, не работает для общих интерфейсов. IFoo Thad

+0

Я нашел способ справиться с этим – Thad

+0

Вы только что спасли меня около 1/2 дня spelunking на MSDN. Спасибо. – dviljoen

0

В то время как я буду первым признаю, что я никогда не пытался присоединить атрибуты интерфейсов, но будет что-то вроде следующей работы для вас?

public abstract class SomeBaseClass: ISomeInterface 
{ 
    [MyAttribute] 
    abstract void MyTestMethod(); 


} 

public SomeClass : SomeBaseClass{ 

    MyAttribute GetAttribute(){ 
     Type t = GetType(); 
     object[] attibutes = t.GetCustomAttributes(typeof(MyAttribute), false); 

     if (attributes.Count() == 0) 
      throw new Exception("could not find MyAttribute defined for " + methodBase.Name); 
     return attributes[0] as MyAttribute; 
    } 


    .... 
} 
2

Метод Марка будет работать для не общих интерфейсов. Но, похоже, что я имею дело с теми, которые имеют дженерики

interface IFoo<T> {} 
class Foo<T>: IFoo<T> 
{ 
    T Bar() 
} 

Оказывается, что Т заменяется фактическим ClassType в map.TargetMethods.

+1

Можете ли вы дать больше информации о том, что такое контекст? Я не могу представить, что вы пытаетесь сделать ... –