2009-09-16 15 views
7

Estoy intentando construir un método de fábrica que use la función de genéricos de C#.Genéricos C# - Restricciones en los parámetros de tipo

En este método de fábrica me gustaría restringirlo a algunas clases específicas, todas las cuales no tienen un constructor predeterminado.

Aquí está mi ejemplo. ¿Puede alguien decirme si es posible ejecutarlo?

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); 
} 

Respuesta

4

Mire la clase Type y GetConstructor. Una vez que obtenga el objeto ConstructorInfo, use el Método Invocar.

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

Esto es lo que solía usar, pero ahora uso 'Activator.CreateInstance' como lo menciona Brian. –

3

No, lo que estamos tratando de hacer no es posible utilizando la incorporada en las limitaciones genéricas por sí solos. La nueva palabra clave solo le permite restringir el tipo genérico a tener un constructor predeterminado.

+0

y solo si se define T: new(). –

4

no creo que se puede crear instancias de tipos genéricos sin a default constructor en el tipo de restricción.

Considere en su lugar especificar una interfaz IAbstractClass, de modo que su clase de fábrica pueda establecer el parámetro SomeClassName como una propiedad de IAbstractClass.

Además, si se requiere una instancia de SomeClassName para inicializar AbstractClass, considere también tener un constructor predeterminado vacío, pero un método de inicialización rico definido en IAbstractClass. Por ejemplo:

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

esta manera, su método estático en lugar BuildObject hace:

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

me gusta usar Activator.CreateInstance(typeof(T)) en mis genéricos que necesitan crear nuevos objetos de tipo T. funciona muy bien.

+0

¡Esto debería ir al podcast .net rocks! gracias por la respuesta. – Pablo

+0

// código final public static T BuildObject (elemento SomeClassUsedForTheConstructor) donde T: SomeAbstractClass { return (T) Activator.CreateInstance (typeof (T), item); } – Pablo

+2

Es lento y no hay verificación en tiempo de compilación ... –

Cuestiones relacionadas