У меня есть интерфейс, который определяет некоторые методы с атрибутами. К этим атрибутам необходимо обращаться из вызывающего метода, но метод, который у меня есть, не извлекает атрибуты из интерфейса. Что мне не хватает?
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;
}
}





MethodBase будет методом класса, а не интерфейсом. Вам нужно будет найти тот же метод в интерфейсе. В C# это немного проще (поскольку он должен иметь одноименное имя), но вам нужно будет рассмотреть такие вещи, как явная реализация. Если у вас есть код VB, это будет сложнее, поскольку метод VB «Foo» может реализовать метод интерфейса «Bar». Для этого вам нужно изучить карту интерфейса:
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;
}
}
Вы только что сэкономили мне примерно полдня, изучая MSDN. Спасибо.
Хотя сначала признаюсь, что я никогда не пробовал прикреплять атрибуты к интерфейсам, но сработает ли для вас что-то вроде следующего?
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;
}
....
}
Метод Марка будет работать для неуниверсальных интерфейсов. Но похоже, что я имею дело с некоторыми, у которых есть дженерики
interface IFoo<T> {}
class Foo<T>: IFoo<T>
{
T Bar()
}
Похоже, что T заменяется фактическим classType в map.TargetMethods.
Не могли бы вы подробнее рассказать о контексте? Я не могу представить себе, что вы пытаетесь сделать ...
Просто проверьте, вы установили соответствующий флаг для своего атрибута, чтобы он мог наследоваться, не так ли?