2009-09-16 14 views
7

Sto provando a creare un metodo factory che utilizza la funzione generics di C#.C# Generics - Vincoli sui parametri del tipo

In questo metodo di produzione, vorrei limitarlo ad alcune classi specifiche, che non hanno un costruttore predefinito.

Ecco il mio esempio. Qualcuno può dirmi se è possibile eseguirlo?

public class AbstractClass { 
    //this abstract class does not have a default constructor, nor its subclasses 
    public AbstractClass(SomeClassName obj) { 
     //use obj for initialization 
    } 
} 

//this factory class should create objects of type T that inherit 
//from AbstractClass and invoke the non-default constructor 
public class FactoryClass { 
    public static T BuildObject<T> (SomeClassName obj) where T: AbstractClass { 
     return new T(obj); //does not work?!?!?! 
    } 
} 


//Edit: ANSWER!!! 
public static T BuildObject<T>(SomeClassUsedForTheConstructor item) where T : SomeAbstractClass { 
return (T) Activator.CreateInstance(typeof (T), item); 
} 

risposta

4

Guarda la classe Type e GetConstructor. Una volta ottenuto l'oggetto ConstructorInfo, utilizzare il metodo Invoke.

var x = typeof(T); 
var t = x.GetConstructor(new[] {obj.GetType()}); 
object u = t.Invoke(<inputs>); 
+0

Questo è quello che usavo, ma ora uso 'Activator.CreateInstance' come menzionato da Brian. –

3

No, ciò che si sta cercando di fare non è possibile utilizzare il built-in da solo vincoli generici. La nuova parola chiave nuova consente di vincolare il tipo generico a un costruttore predefinito.

+0

e solo se T: new() è definito. –

4

non credo che è possibile creare un'istanza tipi generici, senza a default constructor sul tipo di vincolo.

Considerare invece di specificare un'interfaccia IAbstractClass, in modo che la classe factory possa impostare il parametro SomeClassName come una proprietà di IAbstractClass.

Inoltre, se è richiesta un'istanza SomeClassName per l'inizializzazione di AbstractClass, considerare anche un costruttore predefinito vuoto, ma un metodo di inizializzazione avanzato definito in IAbstractClass. Per esempio:

public interface IAbstractClass { void Initialize(SomeClassName obj); } 

In questo modo, il metodo statico BuildObject fa invece:

public static T BuildObject<T>(SomeClassName obj) where T: AbstractClass 
{ 
    T newObject = new T(); 
    IAbstractClass ac = newObject as IAbstractClass; 
    ac.Initialize(obj); 
} 
5

Mi piace usare Activator.CreateInstance(typeof(T)) nei miei farmaci generici che hanno bisogno di creare nuovi oggetti di tipo T. funziona davvero bene.

+0

Questo dovrebbe andare nel podcast .net rocks! Grazie per la risposta. – Pablo

+0

// codice finale public static T BuildObject (voce SomeClassUsedForTheConstructor) dove T: SomeAbstractClass { ritorno (T) Activator.CreateInstance (typeof (T), voce); } – Pablo

+2

È lento e non c'è un controllo in fase di compilazione ... –