2011-01-13 4 views
78

Me gustaría comprobar si un tipo que se conoce en tiempo de ejecución proporciona un constructor sin parámetros. La clase Type no dio nada prometedor, entonces supongo que tengo que usar la reflexión?¿Cómo puedo verificar si un tipo proporciona un constructor sin parámetros?

+0

Creo que es justo – kenny

+2

Nota al margen: Existe una limitación genérica para los constructores sin parámetros. – CodesInChaos

+1

es la pregunta si el tipo ** solo ** proporciona un constructor sin parámetros o si proporciona uno en absoluto? – BrokenGlass

Respuesta

132

El Type clase es la reflexión. Puede hacerlo:

Type theType = myobject.GetType(); // if you have an instance 
// or 
Type theType = typeof(MyObject); // if you know the type 

var constructor = theType.GetConstructor(Type.EmptyTypes); 

Devolverá nulo si no existe un constructor sin parámetros.


Si también quiere encontrar constructores privados, utilice el ligeramente más largo:

var constructor = theType.GetConstructor(
    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, 
    null, Type.EmptyTypes, null); 

Hay una advertencia para los tipos de valor, que aren't allowed to have a default constructor. Puede verificar si tiene un tipo de valor usando la propiedad Type.IsValueType y crear instancias usando Activator.CreateInstance(Type);

+2

esto no encontrará ctors fyi privados –

+2

Esto tampoco funcionará para tipos de valores. – leppie

+2

Comentarios dirigidos arriba. –

12

Sí, tiene que usar Reflection. Pero que ya hace que cuando se utiliza GetType()

Algo así como:

var t = x.GetType(); 
var c = t.GetConstructor(new Type[0]); 
if (c != null) ... 
6

Esto debería funcionar:

myClass.GetType().GetConstructors() 
        .All(c=>c.GetParameters().Length == 0) 
+1

No es lo que quise decir, pero no lo elimine, es un problema relacionado y una buena información. – mafu

1

Sí, tienes que usar la reflexión.

object myObject = new MyType(); 
Type type = myObject.GetType(); 
ConstructorInfo conInfo = type.GetConstructor(new Type[0]); 
3

Dependiendo de su situación, también se puede utilizar una restricción de tipo genérico:

public void DoSomethingWith<T>(T myObject) where T:new() {...} 

La declaración método anterior restringirá el tipo de parámetro a cualquier objeto que puede ser instanciada con un constructor sin parámetros. La ventaja aquí es que el compilador detectará cualquier intento de usar el método con una clase que no tenga un constructor sin parámetros, por lo que siempre que el tipo se conozca EN ALGÚN LUGAR en tiempo de compilación, esto funcionará y lo alertará sobre un problema antes.

Por supuesto, si el tipo realmente se conoce solo en tiempo de ejecución (es decir, si está utilizando Activator.CreateInstance() para instanciar un objeto basado en una cadena o un Type construido), entonces esto no lo ayudará. Generalmente uso el reflejo como la última opción absoluta, porque una vez que has ido a la tierra dinámica, tienes que mantenerte en una tierra dinámica; por lo general es difícil o incluso más complicado crear una instancia dinámica de algo y luego comenzar a tratarlo estáticamente.

+0

En realidad, hay un patrón muy útil para unir los terrenos de invocación estática y dinámica: una clase de almacenamiento en caché genérico estático [p. 'EqualityComparer.Default ']. Para cualquier tipo dado 'T', uno solo tendrá que usar Reflection una vez para construir un objeto cuyo tipo de instancia sea conocido estáticamente para calificar para cualquier restricción requerida, y almacenar una referencia en un campo que no imponga ninguna restricción que un llamador podría no ser capaz de suministrar. – supercat

10

fallarán en struct s. Mejor para extenderla:

public static bool HasDefaultConstructor(this Type t) 
{ 
    return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null; 
} 

tiene éxito ya que incluso tienen enum s constructor sin parámetros por defecto. También se acelera ligeramente para tipos de valores ya que no se realiza la llamada de reflexión.

1

Necesitaba contar constructores con solo parámetros opcionales iguales a los verdaderos constructores sin parámetros.Para ello:

myClass.GetType().GetConstructors() 
    .All(c => c.GetParameters().Length == 0 || c.GetParameters().All(p => p.IsOptional)) 
Cuestiones relacionadas