2012-12-21 8 views
7

Cerco di capire come accedere a un metodo statico entro CallMe<T>() della classe DoSomething. La riflessione è l'unica soluzione qui? Non voglio istanziare un oggetto di tipo MyAction. Inoltre, se lo si fa attraverso la riflessione, esiste un modo per creare il metodo attraverso la riflessione all'interno del metodo CallMe<T>() una sola volta e quindi richiamarlo più volte per eseguire più operazioni sullo stesso metodo "riflesso"? O c'è un modo migliore che attraverso la riflessione? Fondamentalmente voglio creare classi di stile di implementazione del modello come MyAction che definiscono il modo in cui lo byte[] DoThis(string text) svolge il proprio compito. Il AskForSomething() specificherà quindi quale modello viene utilizzato e in base al fatto che lo CallMe<T>() continuerà a funzionare.Passaggio generico e utilizzo, posso eseguire le seguenti operazioni?

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; 
     } 
    } 

risposta

9

Definire un'interfaccia con DoThis, hanno MyAction attuarlo, e vincolare il parametro T tipo da un'istanza di esso con where T : IMyInterface

+1

Nota Suppongo che tu non intenda utilizzare 'DoThis' come metodo statico .. –

+0

+1 Stavo cercando di spiegare perché questo non funziona, ma è apparentemente molto più semplice solo per descrivere come farlo lavoro ... – Rawling

+0

Un'interfaccia è il modo corretto per farlo, ma se si ha _dispositivo il DoThis come metodo statico, allora si dovrà usare la riflessione. –

2

Se il metodo DoThis deve essere statico si può anche cambiare la vostra CallMe metodo per la seguente:

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

Ora si può passare un riferimento a una funzione al CallMe metodo come questo:

doSomething.CallMe(MyAction.DoThis); 
+0

è simile a un delegato o è un delegato? –

+0

Sì, questo è un delegato. È possibile utilizzare questo delegato per rappresentare un metodo che può essere passato come parametro senza dichiarare esplicitamente un delegato personalizzato (vedere [Delega del delegato ] (http://msdn.microsoft.com/en-us/library/bb549151.aspx)) –

+0

grazie per aver spiegato, sapresti per caso quale sia la differenza di prestazioni tra un'implementazione di un delegato e l'interfaccia? Ricordo di aver trovato una domanda simile a questa su SO, ma non riesco a trovarla più. –

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

Tecnicamente corretto, impossibile da cazzare per mantenere e progettare intorno ovviamente :) –

+0

@KierenJohnstone Non stiamo cercando un modo semplice –

+0

Cosa? Sì, tutti gli sviluppatori di software dovrebbero sempre cercare un modo semplice. Puoi usare un paio di forbici per martellare un chiodo - qualcuno potrebbe anche chiedere, qual è il miglior paio di forbici da battere in un'unghia - ma ovviamente, ogni volta, dovresti usare un martello .. –

1

Sulla base del fatto che "dothis" non deve essere statico è possibile raggiungere questo obiettivo con il seguente: -

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; 
    } 
} 
} 

Non sono sicuro io' d consiglio questo approccio ma funziona! (per esempio se non esiste un costruttore predefinito questo fallirà).

+0

È un approccio di riflessione? A proposito, penso che devi chiamare 'doSomething.CallMe ()' invece di 'doSomething.CallMe()', corretto? –

+0

sì, Activator.CreateInstance è effettivamente un riflesso. Puoi usarlo più volte se questo ha senso (ma ricorda il metodo CallMe potrebbe essere chiamato con un tipo diverso rispetto alla chiamata precedente) –

+0

ovviamente altrimenti suppongo che la domanda sarebbe discutibile se non fosse inteso che T fosse di diverso tipo che implementa IMyAction. Grazie però per il fatto di indicarlo. –

Problemi correlati