2014-11-26 17 views
5

Perché voglio evitare un'eccezione, voglio verificare se un tipo ha un costruttore senza parametri. Come posso raggiungere questo obiettivo?Come verificare un tipo per il costruttore senza parametri?

ho bisogno di qualcosa di simile:

bool HasDefaultConstructor<TT>(TT source) 
{ 
    return ???; 
} 

EDIT: Voglio creare un oggetto dello stesso tipo, come fonte e se non ha un costruttore di default che voglio usare di default (TT), invece.

Quello che ho in questo momento è:

 static TT CreateObject<TT>(TT source) 
    { 
     try 
     { 
      if(!HasDefaultConstructor<TT>(source)) 
      { 
       return default(TT); 
      } 
      return (TT)Activator.CreateInstance(source.GetType()); 
     } 
     catch(Exception ex) 
     { 
      Trace.WriteLine("Exception catched!\r\n" + ex); 
     } 
     return default(TT); 
    } 
    static bool HasDefaultConstructor<TT>(TT source) 
    { 
     ConstructorInfo c = typeof(TT).GetConstructor(new Type[] { }); 

     return c != null; 
    } 

Ma l'assegno mi dà la vera e CreateInstance getta eccezione

Nessun costruttore senza parametri

Soluzione:

bool HasDefaultConstructor(Type t) 
{ 
    return t.GetConstructor(Type.EmptyTypes) != null; 
} 

C'erano molte funzioni ricorsive e le iterazioni coinvolte e da qualche parte in questo modo, è stata chiamata la funzione generica errata HasDefaultConstructor (con tipo oggetto). Usare una funzione non generica ha fatto il trucco.

Grazie a tutti per il vostro aiuto costruttivo.

+0

Si prega di chiarire la tua domanda - come si vuole invocare il costruttore? Come ci si aspetta un'eccezione se non esiste un costruttore senza parametri, lo prendo vuoi che il codice sia ancora compilabile anche se il tipo indicato per 'TT' non ha un costruttore simile? –

+0

Se non esiste un costruttore predefinito, desidero utilizzare il valore predefinito (TT). – MTR

+0

Aha! Quindi, per favore, includi queste informazioni nella tua domanda.Cambia significativamente il significato della domanda e rende non valide le risposte che si riferiscono al vincolo generico 'new()' non valido. –

risposta

9

GetConstructor(Type.EmptyTypes) tornerà il costruttore senza parametri, o null se uno non esiste, in modo da avere:

return typeof(TT).GetConstructor(Type.EmptyTypes) != null; 

EDIT

sto cercando di indovinare il problema è che TT e source.GetType() sono in realtà due tipi diversi. source.GetType() deriva probabilmente da TT ma non dispone di un costruttore senza parametri. Così che cosa hai veramente bisogno di fare è rendere il controllo per source.GetType():

bool HasDefaultConstructor(Type t) 
{ 
    return t.GetConstructor(Type.EmptyTypes) != null; 
} 

if(!HasDefaultConstructor(source.GetType())) 
    ... 
+0

Hai ragione. Da qualche parte durante il percorso attraverso alcune funzioni ricorsive le informazioni sul tipo si sono perse. Quindi furono chiamate le generiche funzioni per oggetto (non per il tipo reale) e infatti GetType e TT non erano la stessa cosa. Utilizzando source.GetType() aiutato. – MTR

8

Utilizzare la riflessione per verificare se il tipo ha un costruttore senza parametri. Utilizzare Type.GetConstructor:

bool HasDefaultConstructor<TT>() 
{ 
    ConstructorInfo c = typeof(TT).GetConstructor(new Type[] { }); 
    // A constructor without any types defined: no parameters 

    return c != null; 
} 

Se si desidera solo per creare un'istanza di TT, utilizzare il new vincolo:

TT CreateUsingDefaultConstructor<TT>() where TT : new() 
{ 
    return new TT(); 
} 

Come Jeppe Stig Nielsen suggerito, è possibile utilizzare questo codice per trovare anche costruttori che non sono public. Secondo me, dovresti usare questa come ultima risorsa!

typeof(TT).GetConstructor(BindingFlags.Instance 
          | BindingFlags.NonPublic 
          | BindingFlags.Public 
         , null 
         , new Type[] { } 
         , null 
         ) 
+3

Naturalmente, se si accetta anche un costruttore di parametri zero non pubblici, provare 'typeof (TT) .GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new Scrivi [] {}, null) '. –

+1

@JeppeStigNielsen: aggiunto il tuo suggerimento alla risposta, con attribuzione. –

+0

La versione di HasDefaultConstructor mi dà true, ma la seguente CreateInstance genera un'eccezione. – MTR

Problemi correlati