2013-03-05 4 views
5

Я написал метод, который принимает общий параметр, а затем печатает его свойства. Я использую его для проверки моего веб-сервиса. Он работает, но я хочу добавить некоторые функции, которые я не знаю, как реализовать. Я хочу печатать значения списков, потому что теперь он просто записывает System.Collection.Generic.List1, который ожидается.отражение значений списка и печати

Вот мой код до сих пор, это работает для основных типов (INT, двойные и т.д.):

static void printReturnedProperties<T>(T Object) 
{ 
    PropertyInfo[] propertyInfos = null; 
    propertyInfos = Object.GetType().GetProperties(); 

    foreach (var item in propertyInfos) 
     Console.WriteLine(item.Name + ": " + item.GetValue(Object).ToString()); 
} 
+0

Почему этот метод общий (с '' параметра типа) и вы никогда не используя 'T' для чего-нибудь? –

+0

@HighCore, который он мог бы сделать 'PrintReturnedProperties (подкласс);' –

+5

Вы должны использовать имя параметра, отличное от 'Object', чтобы избавиться от путаницы со встроенным объектом/объектом. –

ответ

5

Вы могли бы сделать что-то вроде этого: (. Я печатая их по одному в строке, но очевидно, что вы можете сделать разные)

static void printReturnedProperties(Object o) 
    { 
     PropertyInfo[] propertyInfos = null; 
     propertyInfos = o.GetType().GetProperties(); 



     foreach (var item in propertyInfos) 
     { 
      var prop = item.GetValue(o); 

      if(prop == null) 
      { 
       Console.WriteLine(item.Name + ": NULL"); 
      } 
      else 
      { 
       Console.WriteLine(item.Name + ": " + prop.ToString()); 
      } 


      if (prop is IEnumerable) 
      { 
       foreach (var listitem in prop as IEnumerable) 
       { 
        Console.WriteLine("Item: " + listitem.ToString()); 
       } 
      } 
     } 


    } 

Он будет перечислять через любой IEnumerable и распечатывать отдельные значения

+0

Я пробовал это, прежде чем я только что сделал что-то не так. Tnx – gorgi93

3

элементов внутри списка могут быть получены с помощью свойства индексатора Item. Это свойство принимает аргумент индекса (есть перегрузка PropertyInfo.GetValue, которые принимают массив object, как и MethodInfo.Invoke) и возвращает объект в этой позиции.

int index = /* the index you want to get here */; 
PropertyInfo indexer = Object.GetProperty("Item"); 
object item = indexer.GetValue(Object, new object[] { index }); 
2

Я обычно печатаю список с , между каждым товаром.

Чтобы сделать это легко, я создал простой метод расширения:

public static class ListEx 
{ 
    public static string StringJoin<T>(this IEnumerable<T> items) 
    { 
     return string.Join(", ", items); 
    } 
} 

Вызвать метод, как myList.StringJoin().

Вы можете, конечно, изменить метод, чтобы использовать другой ограничитель och call напрямую.

+1

Я бы просто использовал 'string.Join (", ", myList)'. – zneak

1

Вот фрагмент, при условии, что ваш список имеет тип T.

foreach (PropertyInfo item in propertyInfos) 
      { 
       Object obj = item.GetValue(object,null); 
       if (!obj.GetType().IsValueType) 
       { 
        if (obj.GetType() == typeof(String)) 
        { 
         Console.WriteLine(obj.ToString()); 
        } 
        else if (obj.GetType() == typeof(List<T>)) 
        { 
         //run a loop and print the list 

        } 
        else if (obj.GetType().IsArray) // this means its Array 
        { 
         //run a loop to print the array 
        } 

       } 
       else 
       { 
        //its primitive so we will convert to string 
        Console.WriteLine(obj.ToString()); 

       } 
1

Я думаю, что вы хотите что-то вроде этого:

public class Program 
{ 
    public static void PrintProperties<T>(T t) 
    { 
     var properties = t.GetType().GetProperties(); 

     foreach (var property in properties) 
     { 
      var name = property.Name; 
      var value = property.GetValue(t, null); 

      if (property.PropertyType.IsGenericType && property.PropertyType == typeof(IEnumerable<>)) 
      { 
       var formatList = typeof(Program).GetMethod("FormatList", new[] { value.GetType() }); 

       // value.GetType().GetGenericArguments().First() will get you the underlying type of the list, 
       // i.e., the TItemType where the property you are currently 
       // handling is of type IEnumerable<TItemType> 
       formatList.MakeGenericMethod(value.GetType().GetGenericArguments().First()); 

       value = formatList.Invoke(null, new object[] { value }); 

       Console.Out.WriteLine(name + ": " + value); 
      } 
      else 
      { 
       Console.Out.WriteLine(name + ": " + value); 
      } 
     } 
    } 

    public static string FormatList<TPlaceholder>(IEnumerable<TPlaceholder> l) 
    { 
     return string.Join(", ", l); 
    } 
} 

код не тестировался, но в принципе, вы хотите решать перечисляемые типы по-разному, по сравнению со скалярными значениями, так как только вы нажмете что-то типа IEnumerable<TItemType>, вы делаете вызов метода FormatList<TPlaceholder>.

Теперь имейте в виду, что ваши оригинальные T и TItemType не обязательно совпадают. Когда вы вызываете FormatList с использованием отражения, вы хотите привязать TPlaceholder к TItemType. Как только вы это сделали, вы просто вызываете метод форматирования и передаете ему фактический экземпляр списка, который возвращает вам строку. Затем эту строку вы можете просто вывести.

Надеюсь, что это поможет.

+0

Мое решение похоже на принятый ответ, признайте, что в принятом ответе мы будем полагаться на метод 'ToString()', дающий что-то разумное, тогда как в моей версии у нас есть немного больше контроля над этим, потому что мы можем разверните 'FormatList()', чтобы сделать что-то более сложное. –

0

Взяв за основу вышеприведенные примеры, вот мое полное решение. Это было протестировано и обрабатывает передачу IEnumerable, распечатывая свойства каждого элемента. Это не рекурсивный, но это достаточно легко добавить.

Помните, что многие из приведенных выше примеров будут разбиваться с индексированными свойствами (например, списками). Parameter count mismatch in property.GetValue().

Этого можно избежать, фильтруя свойства, которые имеют индексированные свойства, используя этот бит LINQ.

Where(x=>!x.GetIndexParameters().Any()) 

Полный пример в виде метода расширения ниже.

/// <summary> 
    /// Returns string representation of object property states i.e. Name: Jim, Age: 43 
    /// </summary> 
    public static string GetPropertyStateList(this object obj) 
    { 
     if (obj == null) return "Object null"; 

     var sb = new StringBuilder(); 
     var enumerable = obj as IEnumerable; 

     if (enumerable != null) 
     { 
      foreach (var listitem in enumerable) 
      { 
       sb.AppendLine(); 
       sb.Append(ReadProperties(listitem)); 
      } 
     } 
     else 
     { 
      sb.Append(ReadProperties(obj)); 
     } 

     return sb.ToString(); 
    } 

    private static string ReadProperties(object obj) 
    { 
     var sb = new StringBuilder(); 
     var propertyInfos = obj.GetType().GetProperties().OrderBy(x => x.Name).Where(x=>!x.GetIndexParameters().Any()); 

     foreach (var prop in propertyInfos) 
     { 
      var value = prop.GetValue(obj, null) ?? "(null)"; 
      sb.AppendLine(prop.Name + ": " + value); 
     } 

     return sb.ToString(); 
    } 
Смежные вопросы