2010-09-19 15 views
12

? Estoy escribiendo algún código de validación. El código tomará los datos pasados ​​a un servicio web y decidirá si puede hacer la acción, o devolverá un mensaje a la persona que llama diciendo que se saltaron algunos campos, etc.¿Cómo trato con matrices usando la reflexión

Lo tengo funcionando principalmente, excepto por las matrices. Estoy marcando las propiedades con un atributo [RequiredField] para representar los campos que se requieren. Entonces, si estos son algunos de mis datos,

public enum EnumTest 
{ 
    Value1, 
    Value2 
} 

[DataContract] 
public class DummyWebserviceData 
{ 
    [DataMember] 
    [RequiredField] 
    public EnumTest[] EnumTest{ get; set; } 

    [DataMember] 
    [RequiredField] 
    public DummyWebserviceData2[] ArrayOfData { get; set; } 
} 

[DataContract] 
public class DummyWebserviceData2 
{ 
    [DataMember] 
    [RequiredField] 
    public string FirstName { get; set;} 

    [DataMember] 
    [RequiredField] 
    public string LastName { get; set;} 

    [DataMember] 
    public string Description { get; set;} 
} 

¿Qué tengo trabajando? Tengo validación de fechas y cadenas funcionando. Utiliza recursividad para llegar a cualquier nivel requerido en los datos.

Pero ... ¿y qué hay de las dos matrices allí? El primero es una matriz de enumeraciones. Quiero comprobar en ese caso que la matriz no está vacía.

El segundo es la matriz de valores DummyWebserviceData2. Necesito sacar cada valor y echarle un vistazo individualmente.

Para simplificar el código que he escrito se ve algo como esto,

foreach (PropertyInfo propertyInfo in data.GetType().GetProperties()) 
{ 
    if (propertyInfo.PropertyType.IsArray) 
    { 
     // this craps out 

     object[] array = (object[])propertyInfo.GetValue(data, new object[] { 0 }); 

    } 
} 

Por lo tanto, me parece que lo primero es que yo puedo decir que es una matriz. ¿Pero cómo puedo saber cuántos elementos hay en la matriz?

Respuesta

19

En tiempo de ejecución del objeto habrá sido una subclase de forma dinámica a partir del tipo de datos Array (this MSDN topic details that), por lo tanto, no es necesario para reflejar en la matriz, se puede emitir el object a Array, y luego usar el Array.GetValue método de instancia:

Array a = (Array)propertyInfo.GetValue(data); 
for(int i = 0; i< a.Length; i++) 
{ 
    object o = a.GetValue(i); 
} 

también puede iterar sobre una matriz como bien - ya que desde .Net 2.0 en adelante:

En .NET Framework versión 2.0, la clase Array implementa las interfaces genéricas System.Collections.Generic :: IList, System.Collections.Generic :: ICollection y System.Collections.Generic :: IEnumerable.

No necesita saber el T, ya que de estos puede obtener un IEnumerable; para lo cual puede usar una operación Cast() o simplemente trabajar en el nivel object.

Por cierto, la razón por la que su código no funciona es porque no se puede lanzar una serie de MyType[] a object[]object[] porque no es un tipo base de MyType[] - Sólo es object.

+0

Solo tenga en cuenta que no puede usar la implementación de la interfaz IList o ICollection para modificar el contenido de la matriz, como dice el tema MDSN antes mencionado. Todos arrojan 'NotSupportedException' –

+1

Correcto. Investigué y encontré muchas de las mismas cosas que mencionas arriba. Lo que sí me aseguré es que el rango de la matriz es de hecho 1. De lo contrario, la matriz podría ser Array [] []. Gracias por tu ayuda. Muy apreciado. – peter

+2

+1 para la sugerencia 'Cast()'. 'MyType [] a = ((Array) propertyInfo.GetValue (data)). Cast () .ToArray();' –

4
foreach (PropertyInfo propertyInfo in data.GetType().GetProperties()) 
{ 
    if (propertyInfo.PropertyType.IsArray) 
    { 
     // first get the array 
     object[] array = (object[])propertyInfo.GetValue(data) 

     // then find the length 
     int arrayLength = array.GetLength(0); 

     // now check if the length is > 0 

    } 
} 
+0

cerca - pero esto no funciona porque 'data' no es la matriz, que es el' object' con una propiedad que es la matriz - el 'propertyInfo' debe ser utilizado para acceder a la matriz primero editado –

+0

para corregir eso ... – Clicktricity

0

La respuesta con la matriz es agradable, pero como se mencionó, no funciona para otros tipos de colecciones. Si no sabe qué tipo es su colección de intentar algo como:

IEnumerable<object> a = (IEnumerable<object>)myPropInfo.GetValue(myResourceObject); 
// at least foreach now is available 
foreach (object o in a) 
{ 
    // get the value 
    string valueAsString = o.ToString(); 
} 
1

Este método funciona bastante bien, y es simple código.

var array = ((IEnumerable)propertyInfo.GetValue(instance)).Cast<object>().ToArray(); 
Cuestiones relacionadas