L’inizializzazione di una Generica variabile da un C# Tipo di Variabile

Ho una classe che richiede un Tipo Generico, come parte della sua inizializzazione.

public class AnimalContext<T>
{
    public DoAnimalStuff()
    {
        //AnimalType Specific Code
    }
}

Quello che posso fare adesso è

AnimalContext<Donkey> donkeyContext = new AnimalContext<Donkey>();
AnimalContext<Orca> orcaContext = new AnimalContext<Orca>();

Ma quello che devo/voglio fare è essere in grado di dichiarare un AnimalContext inizializzato ad un tipo che è noto solo a tempo di esecuzione. Per esempio,

Animal a = MyFavoriteAnimal(); //returns an instance of a class 
                               //implementing an animal
AnimalContext<a.GetType()> a_Context = new AnimalContext<a.GetType()>();
a_Context.DoAnimalStuff();

Questo è anche possibile? Io non riesco a trovare una risposta per questo online.

 

3 Replies
  1. 36

    Che cosa si intende con questa parte è possibile:

    new AnimalContext<a.GetType()>();

    Ovviamente, che la sintassi esatta è sbagliato, e ci riusciremo, ma è possibile creare un’istanza di un tipo generico a runtime quando non si conosce il tipo di parametri, fino a runtime.

    Che cosa si intende con questa parte è non:

    AnimalContext<a.GetType()> a_Context

    Che è, è impossibile per il tipo di una variabile di un tipo generico se non si conosce il tipo di parametri in fase di compilazione. I generici sono in fase di compilazione costrutti, e si basano sul tipo di informazioni disponibili al in fase di compilazione. Dato questo, si perde tutti i benefici dei farmaci generici se non si conoscono i tipi a tempo di compilazione.

    Ora, per costruire un’istanza di un tipo generico a runtime quando non si conosce il tipo fino a runtime, si può dire:

    var type = typeof(AnimalContext<>).MakeGenericType(a.GetType());
    var a_Context = Activator.CreateInstance(type);   

    Di notare che la in fase di compilazione tipo di a_context è object. Si dovrà cast a_context di un tipo o di un interfaccia che definisce i metodi che è necessario per accedere. Spesso ciò che potrete vedere persone fare qui è di tipo generico AnimalContext<T> implementare una qualche interfaccia (dire IAnimalContext) o ereditare da una non generica classe di base (diciamo AnimalContext) che definisce i metodi di cui hanno bisogno (così allora si può lanciare a_context per l’interfaccia o non generico della classe base). Un’altra alternativa è quella di utilizzare dynamic. Ma, ancora una volta, tenere a mente, hai nessuno dei benefici di tipi generici nel fare questo.

    • Tutti coloro che hanno risposto ha dato una risposta che ha fornito un po ‘ di più informazioni rispetto alla precedente risposta. Tutti erano corrette, e di eccellente qualità, ma solo uno può essere selezionato come Risposta, così ho scelto questo che è stato il più descrittivo. Vorrei ringraziare tutti coloro che hanno risposto, però, e apprezzo l’assistenza (appositamente tardi in una notte di domenica.)
    • Cosa succede se la mia Classe non è generico, ma l’interno Metodo è, Come faccio a utilizzare il MakeGenericType in quel caso
    • Di gran lunga il più utile rispondere mai su c# generics. Dopo ore di ricerche salvato così tanto tempo. Grazie mille
  2. 9

    È possibile utilizzare riflessione di tipo generico utilizzando MakeGenericType metodo e prendere adavantage di dynamic parole chiave:

    var type = typeof (AnimalContext<>).MakeGenericType(a.GetType());
    dynamic a_Context = Activator.CreateInstance(type);

    Così si può chiamare:

    a_Context.DoAnimalStuff();

    O utilizzare la riflessione di nuovo metodo di chiamata:

    type.GetMethod("DoAnimalStuff").Invoke(a_Context, null);
  3. 6

    Si avrebbe bisogno di creare il tipo di utilizzo di Riflessione e quindi richiamare quel tipo. Qualcosa come:

    Animal a = MyFavoriteAnimal();
    var contextType = typeof(EsbRepository<>).MakeGenericType(a.GetType());
    
    dynamic context = Activator.CreateInstance(contextType);
    context.DoAnimalStuff();

    L’uso dinamico significa che la variabile di contesto saranno valutati in fase di esecuzione, permettendo chiamare il DoAnimalStuff metodo.

Lascia un commento