Общие коллекции - проверьте, является ли свойство класса одним - PullRequest
0 голосов
/ 03 ноября 2010

Я застрял с простой проверкой типа в универсальном вспомогательном классе, который я пишу. Идея будет понятна, если вы посмотрите на исходный код. Он хорошо работает для обычных вещей, таких как DateTime и bool, но у меня проблема с генериками.

Как мне проверить, например, ObservableCollection <<strong> что-то > и посчитайте это. Я не хочу, чтобы можно было все визуализировать (в конце концов, это отладочный элемент управления), но если есть коллекция, я хочу знать, есть ли в ней элементы.

Пробовал несколько вариантов, но ни один не работал. Не может быть так сложно, поисковые слова просто отстой (общий, список, коллекция) - все не очень дружелюбно к Google: -)

[EDIT]
Хорошо, я немного поигрался и стал ближе. Однако есть странная проблема с функцией GetValue (). Если вы посмотрите на пример класса, свойство с одной строкой работает нормально, то, что установлено в конструкторе, показывает «NULL» - как это может быть. О, кстати. Я работаю в Windows Phone 7 - но это не должно влиять на такие основные вещи, не так ли?
[КОНЕЦ РЕДАКТИРОВАНИЯ]

Обновленная версия моей функции:

        private static FrameworkElement CreateContent(System.Reflection.PropertyInfo propertyInfo, object parent)
    {

        var propValue = propertyInfo.GetValue(parent, null);

        // NULL

        if (propValue == null) return new TextBlock() { Text = "NULL" };

        // Simple cases

        if (propertyInfo.PropertyType == typeof(int))
            return new TextBlock() { Text = propValue.ToString() };

        if (propertyInfo.PropertyType == typeof(DateTime))
            return new TextBlock() { Text = ((DateTime)propValue).ToShortTimeString() };

        if (propertyInfo.PropertyType == typeof(string))
            return new TextBlock() { Text = propValue.ToString() };

        // More exotic cases

        if (typeof(IList).IsAssignableFrom(propValue.GetType()))
                return new TextBlock() {Text = ((IList) propValue).Count.ToString()};

        if (typeof(ICollection).IsAssignableFrom(propValue.GetType()))
            return new TextBlock() { Text = ((ICollection)propValue).Count.ToString() };

        if (typeof(IEnumerable).IsAssignableFrom(propValue.GetType()))
            return new TextBlock() { Text = ((IEnumerable)propValue).Cast<object>().Count().ToString() };

        // If all fails, at least tell me the type

        return new TextBlock() {Text = propertyInfo.PropertyType.Name};
    }

Очень очень странный тестовый пример (ищите StringPropertyA и B)

 public class DebugService : ServiceBase, IDebugService
{
    public DebugService(IUnityContainerPhone container) : base(container)
    {
        DateTimeProperty = DateTime.Now;
        StringEmptyProperty = "";
        StringObsColl = new ObservableCollection<string>() {"A", "B", "C"};
        StringList = new List<string>(){"X", "Y", "Z"};

        StringPropertyB = "Will not show up";

    }

    public override string Description
    {
        get { return "Does nothing, for debug purposes"; }
    }

    public DateTime DateTimeProperty { get; private set; }
    public int IntProperty { get { return 23; } }
    public string StringPropertyA { get {return  "Is OK";}  }
    public string StringPropertyB { get; private set; }
    public string StringEmptyProperty { get; private set; }
    public string StringNullProperty { get; private set; }
    public ObservableCollection<string> StringObsColl { get; private set; }
    public IList<string> StringList { get; private set; }
}

Ответы [ 3 ]

1 голос
/ 03 ноября 2010
propertyInfo.PropertyType.IsAssignableFrom(typeof(IList))

Это классическая ошибка (я думаю, что она настолько распространена из-за синтаксиса value is IList). То, что вы на самом деле хотите, это:

typeof(IList).IsAssignableFrom(propertyInfo.PropertyType)

Существуют и другие вопросы, которые необходимо учитывать, например, хотите ли вы поддерживать другие типы коллекций (не все коллекции будут реализовывать IList.) Если вы особенно заинтересованы в получении доступа к значению в качестве универсальной коллекции, полезный совет является то, что вы можете использовать typeof(IList<>), чтобы получить неспециализированный универсальный тип.

1 голос
/ 03 ноября 2010

Нужно ли идти по этому маршруту?

if (parent is DateTime)
   return new TextBlock() { Text = ((DateTime)parent).ToShortTimeString() };

if (parent is ICollection)
   return new TextBlock() { Text = ((ICollection)parent).Count };

if (parent is IEnumerable)
   return new TextBlock() { Text = ((IEnumerable)parent).Count() }; //assumes System.Linq

...

return new TextBlock() { Text = parent.ToString() };
0 голосов
/ 03 ноября 2010

Я думаю, у вас есть обратный вызов метода IsAssignablefrom. Я думаю, что вы должны сказать typeof(IList).IsAssignableFrom(propertyInfo.PropertyType)

В любом случае, я бы получал объект напрямую и размышлял о нем, а не размышлял о типе свойства. Таким образом, если у вас есть свойство типа object, которое возвращает список, оно будет правильно отображаться в вашем элементе управления отладкой.

private static FrameworkElement CreateContent(System.Reflection.PropertyInfo propertyInfo, object parent)
{
    object propValue = propertyInfo.GetValue(parent, null);

    if (propValue is ICollection)
        return new TextBlock() { Text = ((ICollection)propValue).Count.ToString() };
    else if (propValue is ...)
        return new TextBlock() { Text = ... };
    else
        return new TextBlock() { Text = propValue.ToString() };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...