2016-04-23 17 views
2

Ich habe ein Anforderungsattribut, dass ich einige Dienste dekoriere, aber ich muss einen generischen Typ in es eingeben, weil etwas Logik darin passiert. Es sieht so aus:Übergeben/Aussetzen von T auf einem ServiceStack-Anforderungsfilter

[SomeAttribute(typeof(MyClass))] 

Dies funktioniert gut, aber wenn ich etwas tun, wie ...

[SomeAttribute<MyClass>] 

... Ich werde ein bekommen „Annotations nicht generisch sein“ Kompilierung Zeitfehler.

In meinem Attribut Logik auszuführen, muss ich folgendes tun:

someClass.doSomething<MyClass>(someString); 

Also, meine Frage ist ...

  • Kann ich werfen MyClass zu irgendeiner Form von T so kann ich benutzt es so?
  • Gibt es eine andere Möglichkeit, die ich T im Attribut übergeben kann, ohne einen Kompilierungsfehler zu bekommen?

Vielen Dank!

Antwort

4

Wie die Fehlermeldungen sagt .NET-Anmerkungen können nicht generisch sein, so dass Sie nur eine spät gebunden Type übergeben können. Der einzige Weg, eine generische Methode aus einem spät gebundenen Typ zu nennen, ist Reflexion zu verwenden, zB:

var mi = typeof(MyClass).GetMethod("doSomething"); 
var genericMi = mi.MakeGenericMethod(typeof(MyAttributeType)); 
var doSomethingFn = (Func<string, object>) genericMi.CreateDelegate(
    typeof(Func<string, object>)); 

Dann können Sie die kompilierte Delegierter der generischen Methode Cache und rufen die ein string nimmt und gibt ein object, zB:

object response = doSomethingFn(someString); 
+0

Danke für die Antwort, @mythz! Also, ich sehe, wohin du gehst ... und es macht ziemlich viel Sinn. In Ihrem Beispiel wird jedoch eine Laufzeitausnahme von "method arguments incompatible" auf "doSomethingFn" ausgelöst. – napo

+0

PS: Da Sie hinter ServiceStack sind, hier ein bisschen mehr Kontext ... Ich versuche, Caching über ein Attribut zu implementieren, 'this.cache.Get (" Schlüssel ")' ist, wo ich versuche zu bekommen zu. Oh, und mit Mono, FYI ... Macht Sinn? Und nochmals vielen Dank! – napo

+1

@napo Es muss eine Wrapper-Methode aufgerufen werden, die ein 'Objekt' anstelle der generischen 'T'-Antwort zurückgibt, siehe [ServiceGatewayExtensions] (https://github.com/ServiceStack/ServiceStack/blob/f4c9606b17dae06c7af193d7661dfa2b31d8b722/src /ServiceStack.Client/ServiceGatewayExtensions.cs#L30), die im Wesentlichen dasselbe tut. Dies funktioniert genau so in Mono. Andernfalls können Sie es direkt mit Reflection aufrufen, d. H. Ohne den Delegaten zwischenzuspeichern, z. B .: 'genericMi.Invoke (this.cache, new [] {someString})'. – mythz