tags:

views:

52

answers:

2

Hi All,

I am writing some validation code. The code will take data passed into a web service and decide whether it can do the action, or return a message to the caller that they have missed out some fields etc.

I have it mostly working except for arrays. I am marking up the properties with a [RequiredField] attribute to represent fields that are required. So if this is some of my data,

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

So what do I have working? I have validation of dates, and strings working. It uses recursion to go any level deep required on the data.

But ... so what about the two arrays there. The first is an array of enums. I want to check in that case that the array is not empty.

The second is the array of DummyWebserviceData2 values. I need to pull each value out and have a look at it individually.

To simplify the code I have written it looks something like this,

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

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

    }
}

So it seems to me that the first thing is that I can tell it is an array. But how then can I tell how many items are in the array?

+1  A: 
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

    }
}
Clicktricity
close - but this won't work because `data` is not the array, it's the `object` with a property that is the array - the `propertyInfo` must be used to access the array first
Andras Zoltan
edited to correct that...
Clicktricity
+2  A: 

At runtime the object will have been dynamically subclassed from the Array data type (this MSDN topic details that), therefore you don't need to reflect into the array, you can cast the object to Array, and then use the Array.GetValue instance method:

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

You can also iterate over an array as well - since from .Net 2.0 onwards:

In the .NET Framework version 2.0, the Array class implements the System.Collections.Generic::IList, System.Collections.Generic::ICollection, and System.Collections.Generic::IEnumerable generic interfaces.

You don't need to know the T, since from these you can get an IEnumerable; which you can then use a Cast() operation on, or indeed just work at the object level.

Incidentally, the reason why your code isn't working is because you can't cast an array of MyType[] to object[] because object[] is not a base type of MyType[] - only object is.

Andras Zoltan
Just note that you can't use the IList or ICollection interface implementation to modify the array contents - as the aforementioned MDSN topic states - they all throw `NotSupportedException`
Andras Zoltan
Correct. I researched and came across much of the same stuff you mention above. What I did make sure too is that the array rank is indeed 1. Otherwise the array could be Array[][]. Thanks for your help though. Much appreciated.
peter
+1 for the `Cast()` suggestion. `MyType[] a = ((Array)propertyInfo.GetValue(data)).Cast<MyType>().ToArray();`
Callum Rogers
@peter - good point there about the rank of the array
Andras Zoltan