2012-12-21 4 views
7

Ich versuche herauszufinden, wie ich auf eine statische Methode innerhalb CallMe<T>() der Klasse DoSomething zugreifen kann. Ist Reflexion die einzige Lösung hier? Ich möchte kein Objekt vom Typ MyAction instanziieren. Auch wenn es durch Reflexion getan wird, gibt es eine Möglichkeit, die Methode durch Reflexion innerhalb der Methode CallMe<T>() nur einmal zu erstellen und sie dann mehrmals aufzurufen, um mehrere Operationen mit derselben "reflektierten" Methode auszuführen? Oder gibt es einen besseren Weg als durch Reflexion? Ich möchte im Grunde erstellen Template-Implementierung Stil Klassen wie MyAction, die definieren, wie byte[] DoThis(string text) seine Pflicht erfüllt. Die AskForSomething() wird dann angeben, welche Vorlage verwendet wird und entsprechend wird die CallMe<T>() über ihre Arbeit gehen.Generische Art und Weise der Weitergabe und Verwendung, kann ich folgendes tun?

public class AskSomething 
    { 
     public void AskForSomething() 
     { 
      DoSomething doSomething = new DoSomething(); 
      doSomething.CallMe<MyAction>(); 
     } 
    } 

    public class DoSomething 
    { 
     public void CallMe<T>() 
     { 
      Type type = typeof(T); 

      //Question: How can I access 'DoThis(string text)' here? 
      //Most likely by reflection? 
     } 
    } 

    public class MyAction 
    { 
     public static byte[] DoThis(string text) 
     { 
      byte[] ret = new byte[0]; //mock just to denote something is done and out comes a byte array 

      return ret; 
     } 
    } 

Antwort

9

definieren eine Schnittstelle mit DoThis haben MyAction es umzusetzen, und beschränken den T Typ-Parameter eine Instanz mit where T : IMyInterface

+1

Hinweis Ich gehe davon aus, dass Sie 'DoThis' nicht als statische Methode haben wollen. –

+0

+1 Ich habe versucht zu erklären, warum das nicht funktioniert, aber es ist anscheinend viel einfacher, nur zu beschreiben, wie man es macht Arbeit ... – Rawling

+0

Eine Schnittstelle ist der richtige Weg, um dies zu tun, aber wenn Sie die DoThis als statische Methode haben müssen, dann müssen Sie die Reflexion verwenden. –

2

werden, wenn Ihr DoThis Methode statisch sein muss können Sie auch Ihre CallMe ändern Verfahren auf die folgenden:

public void CallMe(Func<string, byte[]> action) 
{ 
    byte[] result = action("input"); 
} 

Jetzt können Sie einen Verweis auf eine Funktion, um diepassieren kann 10 Verfahren wie folgt aus:

doSomething.CallMe(MyAction.DoThis); 
+0

ist das ähnlich wie ein Delegat oder ist ein Delegierter? –

+0

Ja, das ist ein Delegierter. Sie können diesen Delegaten verwenden, um eine Methode darzustellen, die als Parameter übergeben werden kann, ohne explizit einen benutzerdefinierten Delegaten zu deklarieren (siehe [Func Delegat] (http://msdn.microsoft.com/en-us/library/bb549151.aspx)) –

+0

danke für die Erklärung, würdest du zufälligerweise zufällig wissen, was der Leistungsunterschied zwischen einer Delegierten- und Schnittstellenimplementierung ist? Ich erinnere mich, dass ich eine ähnliche Frage zu SO hatte, aber ich kann sie nicht mehr finden. –

0
public class DoSomething 
    { 
    class Cache<T> 
    { 
     public readonly static Func<string, byte[]> action = (Func<string, byte[]>)Delegate.CreateDelegate(typeof(Func<string, byte[]>), typeof(T).GetMethod("DoThis")); 
    } 
    public void CallMe<T>() 
    { 
     Cache<T>.action("text"); 
    } 
    } 
+0

Technisch korrekt, unglaublich Mist, um natürlich zu warten und zu gestalten :) –

+0

@KierenJohnstone Wir suchen keinen einfachen Weg –

+0

Was? Ja, alle Softwareentwickler sollten immer nach einem einfachen Weg suchen. Sie können eine Schere benutzen, um einen Nagel einzuhämmern - jemand könnte sogar fragen, was die beste Schere ist, um einen Nagel einzuhämmern - aber natürlich sollten Sie jedes Mal einen Hammer verwenden. –

1

Basierend auf der Tatsache, dass „DoThis“ muss nicht statisch sein Sie dies mit dem folgenden erreichen: -

using System; 

namespace ConsoleApplication3 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     DoSomething doSomething = new DoSomething(); 
     doSomething.CallMe<MyAction>(); 

    } 
} 
public class DoSomething 
{ 
    public void CallMe<T>() where T : IMyAction 
    { 
     IMyAction action = (IMyAction)Activator.CreateInstance(typeof(T)); 

     var result = action.DoThis("value");    
    } 
} 

public interface IMyAction 
{ 
    byte[] DoThis(string text); 
} 

public class MyAction : IMyAction 
{ 
    public byte[] DoThis(string text) 
    { 
     byte[] ret = new byte[0]; //mock just to denote something is done and out comes a byte array 

     return ret; 
    } 
} 
} 

nicht sicher, ob ich‘ Ich empfehle diesen Ansatz, aber es funktioniert! (Wenn zum Beispiel kein Standardkonstruktor vorhanden ist, wird dies fehlschlagen).

+0

Ist dies ein Reflexionsansatz? Btw, ich denke du musst 'doSomething.CallMe ()' anstelle von 'doSomething.CallMe()' aufrufen, richtig? –

+0

ja, die Activator.CreateInstance ist effektiv Reflexion. Sie können es mehrere Male verwenden, wenn das Sinn macht (aber denken Sie daran, die Methode CallMe könnte mit einem anderen Typ als der vorherige Aufruf aufgerufen werden) –

+0

natürlich sonst würde ich die Frage wäre mot, wenn es nicht beabsichtigt, T verschiedene Typen haben die implementieren IMyAction. Danke, dass Sie darauf hingewiesen haben. –

Verwandte Themen