1

I successfully implemented the answer on this question. However, it does not work when I have a List. When I ran this through, here's what I got back:

AccountDataResult: 'AccountFound'
AccountList: 'CustomWebService.TestApplication.ServiceMethods.CustomClassOutputData+DataList[]'

This list has X items inside and I need to list out all of the properties for each one. What is the best method to achieve this?

Here is what I have today:

void AddPropertiesToTextbox(object output, TextBox txt)
{
   PropertyInfo[] piData = null;
   piData = Utility.GetPublicProperties(output.GetType());

   foreach (PropertyInfo pi in piData)
   {
      if (pi.Name.ToLower() != "extensiondata")
      {
         textResult.Text += string.Format("{0}: '{1}'", pi.Name, pi.GetValue(output, null));
         textResult.Text += Environment.NewLine;
      }
   }
}

Here is my web service Model:

[DataContract]
public class OutputData
{
    [DataContract]
    public class AccountData
    {
        [DataMember]
        public string AccountStatus { get; set; }

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

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

    }

    [DataContract]
    public enum AccountDataResults
    {
        [EnumMember]
        None,
        [EnumMember]
        AccountFound,
        [EnumMember]
        NoAccounts
    }

    [DataMember]
    public List<AccountData> DataList { get; set; }

    [DataMember]
    public AccountDataResults AccountDataResult { get; set; }
}
Community
  • 1
  • 1
Kyle Crabtree
  • 198
  • 1
  • 10

3 Answers3

1

You can check the PropertyInfo's PropertyType type definition by calling GetGenericTypeDefinition()

if(pi.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
{
   // recurse through properties
}
SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
0

Demo:

class Program
{
    static void Main(string[] args)
    {
        object test = new Test { DemoProperty = "Some", DemoListProperty = new List<int> { 1, 2, 3, 4 } };

        Type type = typeof(Test);
        foreach (var pi in type.GetProperties())
        {
            if (pi.PropertyType.IsGenericType && pi.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
            {
                IEnumerable objects = pi.GetGetMethod().Invoke(test,null) as IEnumerable;
                foreach (var o in objects)
                {
                    Console.WriteLine(o); //may want to do recursion here and iterate over these properties too
                }
            }
        }
    }
}

class Test
{
    public string DemoProperty { get; set; }
    public List<int> DemoListProperty { get; set; }
}
Florian Schmidinger
  • 4,682
  • 2
  • 16
  • 28
  • This does not seem to work when dealing with a class from a web service. I copy/pasted your code in my program and ran it and it seems to work, but when I change: Type type = typeof(MyOutputClass); It no longer pulls any properties. – Kyle Crabtree Mar 16 '15 at 13:42
  • Its just a demo... use your existing code to get the infos and use this if block – Florian Schmidinger Mar 16 '15 at 13:45
  • @KyleCrabtree did you try to put a breakpoint in the if block? Does it enter the block? – Florian Schmidinger Mar 16 '15 at 13:48
  • I updated the original question with my Model, which may help understand. After changing to my class from the web service, the pi.PropertyType.IsGenericType = false, which is why it never returns any data. – Kyle Crabtree Mar 16 '15 at 13:51
  • @KyleCrabtree so what type are you getting when you reached the List property? – Florian Schmidinger Mar 16 '15 at 13:53
  • The full type is CustomWebService.TestApplication.ServiceMethods.CustomClassOutputData+DataList[]. When I skip over the if (pi.PropertyType.IsGenericType) then I can loop through all o in objects. – Kyle Crabtree Mar 16 '15 at 14:16
  • @KyleCrabtree Well the 'as Enumerable' would make the objects variable null if it isn't a Enumeration therefor you can check if its a List<> ... not sure youll get exceptions on occasion though – Florian Schmidinger Mar 16 '15 at 14:20
0

In order to get this working I had to scrap my initial setup. Here is what I am doing now. This works PERFECTLY for me! This was used to pull all properties i care about into a result list.

Get all properties for any type:

public static PropertyInfo[] GetPublicProperties2(this Type type)
{
    return type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
}

I then have this method that is generic for any property which calls itself when there is an array.

void AddPropertiesToTextbox(object output, string rootNamespace = "")
    {
        PropertyInfo[] piData = null;
        piData = Utility.GetPublicProperties2(output.GetType());

        foreach (PropertyInfo pi in piData)
        {
            if (pi.PropertyType.IsArray == true)
            {
                Array subOutput = (Array)pi.GetValue(output);


                for (int i = 0; i < subOutput.Length; i++)
                {
                    textResult.Text += string.Format("{0}------------------------{0}", Environment.NewLine);
                    object o = subOutput.GetValue(i);
                    AddPropertiesToTextbox(o, pi.Name);
                }
            }
            else
            {
                if (pi.Name.ToLower() != "extensiondata")
                {
                    if (string.IsNullOrWhiteSpace(rootNamespace) == false) {
                        textResult.Text += string.Format("{2}.{0}: '{1}'", pi.Name, pi.GetValue(output, null), rootNamespace);
                    textResult.Text += Environment.NewLine;
                    } else {
                        textResult.Text += string.Format("{0}: '{1}'", pi.Name, pi.GetValue(output, null));
                    textResult.Text += Environment.NewLine;
                    }

                }
            }
        }
    }
Kyle Crabtree
  • 198
  • 1
  • 10