2015-05-01 12 views
7

Posso utilizzare il parametro di tipo come interfaccia specifica di implementazione in Runtime senza Reflection? Il seguente pseudocodice è ciò che voglio fare.C'è un modo per trasmettere il parametro type?

void Run1<T>() 
{ 
    // ... 
    if (typeof (IEnumerable).IsAssignableFrom (typeof (T)) { 
     Run2<T implementing IEnumerable>(); // <- use T as implementing IEnumerable 
    } 
    // ... 
} 

void Run2<T>() where T : IEnumerable 
{ 
    // ... 
} 

risposta

4

No, non credo che ci sia un modo semplice per farlo.

Se siete in controllo di tutto il codice, si potrebbe avere una versione pubblica della Run2 con il vincolo, ma un privata attuazione Run2 senza il vincolo, che voi chiamate da Run1:

public void Run1<T>() 
{ 
    // ... 
    if (typeof(IEnumerable).IsAssignableFrom(typeof(T)) 
    { 
     Run2Impl<T>(); 
    } 
    // ... 
} 

public void Run2<T>() where T : IEnumerable 
{ 
    Run2Impl<T>(); 
} 

private void Run2Impl<T>() 
{ 
    // Need to cast any values of T to IEnumerable here 
} 
+0

Con un po 'di riflessione, sembra che non è così difficile. – Alex

+0

@Alex: Sì, si può fare con la riflessione - ma l'OP chiedeva specificatamente una soluzione senza usare la riflessione. –

+0

Oops, non ho letto abbastanza bene la domanda – Alex

1

Se si dovesse abbandonare l'esigenza di non utilizzare il riflesso, è possibile farlo utilizzando una piccola deviazione.

public class Tester 
{ 
    private static readonly MethodInfo _run2Method = typeof(Tester).GetMethod("Run2"); 

    public void Run1<T>() 
    { 
     if (typeof(IEnumerable).IsAssignableFrom(typeof(T))) 
      Run2AsIEnumerable<T>(); 
     else 
      Console.WriteLine("Run1 for {0}", typeof(T)); 
    } 

    public void Run2<T>() where T : IEnumerable 
    { 
     Console.WriteLine("Run2 for {0}", typeof(T)); 
    } 

    private void Run2AsIEnumerable<T>() 
    { 
     Console.WriteLine("Detour to run2 for {0}", typeof(T)); 
     var method = _run2Method.MakeGenericMethod(typeof(T)); 
     method.Invoke(this, new object[0]); 
    } 
} 

Si noti che questo potrebbe essere reso un po 'più efficiente costruendo e memorizzando nella cache i delegati per tipi specifici su richiesta.

L'uscita di questo:

new Tester().Run1<IEnumerable<int>>(); 

è:

Detour to run2 for System.Collections.Generic.IEnumerable`1[System.Int32] 
Run2 for System.Collections.Generic.IEnumerable`1[System.Int32] 
Problemi correlati