Creare un oggetto sapendo solo il nome della classe?

Ho un set di classi, ognuno è diverso strategia per fare lo stesso lavoro.

namespace BigCorp.SuperApp
{
    public class BaseClass { }
    public class ClassA : BaseClass { }
    public class ClassB : BaseClass { }
}

La scelta della strategia da utilizzare è configurabile. Voglio configurare solo il nome della classe ‘ClassB’ invece del nome completo del tipo ‘BigCorp.SuperApp.ClassB’ in app.file di configurazione.

<appConfig>
   <SuperAppConfig>
      <Handler name="ClassB" />
   </SuperAppConfig>
</appConfig>

Tuttavia, la riflessione fallire perché si aspettano che il nome completo del tipo, in particolare

Type t = Type.GetType("ClassB"); //results in t == null
BaseClass c = Activator.CreateInstance(t) as BaseClass; //fails

Come posso ottenere questo lavoro durante la configurazione solo il nome della classe? Concatenare lo spazio dei nomi per il nome della classe per il nome completo del tipo? C’è un’altra riflessione chiamata che funziona?

Se si pensa che questo è inutile e mi aspetto che la configurazione di contenere il nome completo del tipo, io sono aperto a questa soluzione! Basta fornire motivazioni per convincere me.

(Non sarò il caricamento di un tipo al di fuori di questa assemblea/spazio dei nomi)

  • Potrei utilizzare un contenitore IoC, trattare con i nomi lunghi, e ottenere la creazione di un oggetto fatto per me!

 

5 Replies
  1. 6

    In quanto è a conoscenza di tutte le classi saranno provenienti da uno stesso spazio dei nomi, configurare e utilizzare che:

    <appConfig>
       <SuperAppConfig handlerNamespace="BigCorp.SuperApp">
          <Handler class="ClassB" />
       </SuperAppConfig>
    </appConfig>

    Edit: ho cambiato nome per classe per meglio indicare il significato di tale attributo.

    • Apprezzo le risposte, il codice e la discussione dell’assemblea di carico. Ma mi piace Bryan risposta per la messa a fuoco su di configurazione (visto che non possono allontanarsi dal nome completo del tipo).
  2. 18

    Utilizzare assemblea-completo-nome, o entrare in possesso di il Montaggio e l’uso Assembly.GetType(name). In questo caso, poiché si desidera che i tipi nel file di configurazione, montaggio qualificato è un valido modo per andare – ma dal momento che si sa che tutti i vostri tipi sono nella stessa assemblea:

    Assembly assembly = typeof(SomeKnownType).Assembly; //in the same assembly!
    Type type = assembly.GetType(name); //full name - i.e. with namespace (perhaps concatenate)
    object obj = Activator.CreateInstance(type);

    Statico Type.GetType(string) ha tastatura regole che sono spesso causa di confusione… guarda la convocazione dell’assemblea e del sistema parlamentare – ma non tutti gli assembly caricati.

    • Ho un servizio di riferimento che voglio chiamare usando questo, ma non è visibile nell’elenco tipo di montaggio (fatto con la classe). Anche se posso creare un oggetto di riferimento chiamando il costruttore codificare.
  3. 5
    (Non sarò il caricamento di un tipo al di fuori di questa assemblea/spazio dei nomi)

    a causa del al di sopra della linea, si può dare per scontato che si sappia cosa lo spazio dei nomi è. Non è che puoi fare qualcosa di simile:

    Type t = Type.GetType("Namespace." + className); 
    BaseClass c = Activator.CreateInstance(t) as BaseClass; 

    Se si prevede che, eventualmente, essere in grado di aggiungere ulteriore strategia classi per essere caricati in futuro, forse per via di un montaggio, è necessario qualificare completamente il nome della classe. Questo è consigliato comunque, dato che si sarebbe in grado di fornire una migliore extendability per la vostra applicazione.

    • Che in realtà dipende da dove il codice è (e come si interpretano “dal di fuori” – cioè che la classe? o il chiamante?). Senza un assembly nome completo, Tipo.GetType(stringa) sarà solo guarda il corrente assieme e un sistema di assemblee. Non trovare i tipi casuale di riferimento dll.
  4. 2

    Sto andando con il nome completo del tipo nella configurazione dell’applicazione. Qui di seguito è un po ‘ più completo, ma ancora banale esempio

    <SuperAppConfig>
       <ObjectConfig provider="BigCorp.SuperApp.ClassA">
          <add name="one" />
          <add name="two" />
       </ObjectConfig>
    </SuperAppConfig>

    E la fabbrica di classe che crea effettivamente questo

    private static Assembly a = typeof(IFactoryObject).Assembly;
    public static IFactoryObject CreateObject(String providerName)
    {
        Type t = a.GetType(providerName)
        IFactoryObject o = Activator.CreateInstance(t) as IFactoryObject;
        return o;
    }
  5. 1
    BaseClass c = Activator.CreateInstance(t) as BaseClass; //fails

    Potrebbe anche derivare dal fatto, che CreateInstance non restituisce un’istanza di BaseClass, piuttosto che un’istanza di BaseClass avvolto in un ObjectHandle.

    Cast nel tuo BaseClass dopo aver utilizzato l’UnWrap metodo.

Lascia un commento