2010-05-12 13 views
9

Estoy escribiendo una herramienta donde tengo que reflexionar sobre los métodos y si los parámetros de los métodos son de tipo complejo, entonces necesito cierto tipo de acciones como instanciarlas, etc.determinar el tipo complejo de un tipo primitivo utilizando la reflexión

Ahora vi la propiedad IsPrimitive en la variable Type. Sin embargo, muestra string y decimal como tipos complejos, que técnicamente no es incorrecto. Sin embargo, lo que realmente quiero es poder distinguir los tipos de clase creados por el desarrollador de los tipos de datos definidos por el sistema.

¿Hay alguna manera de que pueda hacer esto?

Respuesta

8

decimal sin duda es un "tipo complejo"; C# puede tener una palabra clave para ello, pero no es una primitiva CLI. String, podría argumentar de cualquier manera: en realidad es un tipo para sí mismo (tamaño indeterminado, etc.), las únicas cosas remotamente comparables son las matrices.

Sin embargo; simplemente no hay forma de determinar lo que quieres aquí. El mejor que puede hacer es comprobar conocidos conjuntos de sistema (o tal vez la firma de claves). Después de todo, me puede escribir una asamblea llamada System.something.dll o Microsoft.something.dll, con tipos en el espacio de nombres System.Foo.Bar (esto también depende de la forma paranoide que desea ser, por supuesto).

Puede ser más fácil hacer que los desarrolladores marquen explícitamente sus propios tipos que desea tratar de manera específica, ya sea a través de un atributo o una interfaz.

+0

En C#, las cadenas son tipos claramente complejos. Se definen como una clase en lugar de stuct que solo marca la diferencia, pero el comportamiento de la cadena tampoco es conceptualmente primitivo. Su uso en C# se parece al de un tipo primitivo, pero eso se hace principalmente a través de una sobrecarga inteligente del operador y algunas características especiales del lenguaje (como el manejo de C# de los literales de cadena). –

+0

@Stephen - No estoy de acuerdo; struct vs class es * no * lo importante aquí. Puedo escribir una estructura personalizada tanto como un tipo, etc. Y lo "especial" en la cadena va mucho más allá del lenguaje, como los operadores. –

+0

Creo que podría ser semántica en función de su definición de "complejo", y C# no utiliza oficialmente el término "tipo complejo". Tiene términos como "personalizado" y "tipo de valor", y las picaduras no lo son. Los considero conceptualmente complejos porque los datos de cadenas se almacenan como una matriz de elementos que no son cadenas ... por lo tanto, el uso de datos en una cadena depende del comportamiento que es más complejo que una simple obtención de los tipos de valores subyacentes de memoria. Pero su definición de complejo puede ser diferente. –

0

No estoy seguro de cómo utilizar los tipos incorporados es diferente de los tipos creados por el usuario. Su problema más grande sería crear instancias de tipos que no tienen constructores sin parámetros.

Hagas lo que hagas, tendrás que convertirlos en matrices de objetos para que puedas pasarlos a MethodInfo.Invoke, por lo que en algún momento tendrás que hacer Activator.CreateInstance.

Si proporciona una IU donde un usuario puede ingresar cosas en los campos y luego presiona un botón para llamar a un método, la mejor estrategia sería usar Reflection para buscar los métodos estáticos TryParse/Parse en el tipo y llamar a aquellos para validar/analizar la entrada.

Aquí hay un fragmento que va a funcionar de forma implícita para la mayoría de los tipos de sistemas que se pueden convertir de cadena:

var parseMethod = typeof(int).GetMethods().FirstOrDefault(
    m => m.IsStatic && 
     m.Name == "TryParse" && 
     m.GetParameters().Length == 2 && 
     m.GetParameters()[0].ParameterType == typeof(string) && 
     m.GetParameters()[1].IsOut); 
if(parseMethod != null) { 
    bool result = (bool)parseMethod.Invoke(null, new object[]{"45", null}); 
    //result == true 
    result = (bool)parseMethod.Invoke(null, new object[] { "blah", null }); 
    //result = false 
} 
+0

Realmente crear instancias de tipos sin un constructor sin parámetros (ni siquiera uno privado) no es tan grande, * pero * debe tener mucho cuidado; no recomendado para la mayoría del código, solo es realmente adecuado para cosas como las API de serialización. –

+0

Oh genial, no sabía que pudieras hacer eso. –

2

No estoy seguro de si hay un método más elegante, pero imagino que si comprueba el Namespace o el AssemblyQualifiedName del tipo frente al sistema de espacio de nombres y/o los ensamblajes del sistema, funcionará bien.

4

Encontré este hilo mientras estaba haciendo una búsqueda. Estaba buscando una solución para esto y descubrí que también puede verificar los espacios de nombres para ver si la propiedad se ha definido en su propio espacio de nombres.

if (property.PropertyType.Namespace.StartsWith("MyApp.MyNamespace")) 
{ 
     // logic for properties in MyNamespace 
} 

Espero que esto ayude a alguien.

Cuestiones relacionadas