Attribute auf einer Schnittstelle
-
05-07-2019 - |
Frage
Ich habe eine Schnittstelle, die einige Methoden mit Attributen definiert. Diese Attribute müssen von der rufenden Methode zugegriffen werden, aber die Methode, die ich habe nicht zieht die Attribute aus der Schnittstelle. Was bin ich?
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;
}
}
Lösung
Die Method wird die Methode für die Klasse, nicht die Schnittstelle. Sie werden nach der gleichen Methode auf der Schnittstelle zu suchen. In C # ist dies ein wenig einfacher (da es wie Namen muss sein), aber Sie würde Dinge wie explizite Implementierung berücksichtigen müssen. Wenn Sie VB-Code haben wird es schwieriger sein, da VB-Methode „Foo“ kann eine Interface-Methode „Bar“ implementieren. Dazu müssen Sie die Schnittstelle Karte untersuchen:
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;
}
}
Andere Tipps
Mark-Methode für nicht-generische Schnittstellen arbeiten. Aber es scheint, dass ich mit einigen zu tun habe, die Generika haben
interface IFoo<T> {}
class Foo<T>: IFoo<T>
{
T Bar()
}
Es scheint, dass die T mit dem tatsächlichen Classtype in dem map.TargetMethods ersetzt wird.
Während ich zunächst gestehen, dass ich nie versucht, Attribute Schnittstellen zu befestigen, sondern würde so etwas wie die folgende Arbeit für Sie?
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;
}
....
}