IEnumerable <T>и отражение - PullRequest
       63

IEnumerable <T>и отражение

1 голос
/ 10 мая 2010

Фон

Работа в .NET 2.0 Здесь отображаются списки в целом. Первоначально я использовал t.IsAssignableFrom(typeof(IEnumerable)), чтобы определить, поддерживает ли обходимое мной свойство интерфейс IEnumerable. (И, таким образом, я мог безопасно прикрепить объект к нему)

Однако этот код не оценивался до True, когда объект является BindingList<T>.

Далее

Я пытался использовать t.IsSubclassOf(typeof(IEnumerable)), но мне тоже не повезло.

Код

    /// <summary>
    /// Reflects an enumerable (not a list, bad name should be fixed later maybe?)
    /// </summary>
    /// <param name="o">The Object the property resides on.</param>
    /// <param name="p">The Property We're reflecting on</param>
    /// <param name="rla">The Attribute tagged to this property</param>
    public void ReflectList(object o, PropertyInfo p, ReflectedListAttribute rla)
    {
        Type t = p.PropertyType;
        //if (t.IsAssignableFrom(typeof(IEnumerable)))
        if (t.IsSubclassOf(typeof(IEnumerable)))
        {
            IEnumerable e = p.GetValue(o, null) as IEnumerable;

            int count = 0;
            if (e != null)
            {
                foreach (object lo in e)
                {
                    if (count >= rla.MaxRows)
                        break;

                    ReflectObject(lo, count);

                    count++;
                }
            }
        }
    }

Намерение

Я хочу в основном пометить списки, которые я хочу отразить с помощью ReflectedListAttribute, и вызвать эту функцию для свойств, которые ее имеют. (Уже работает)

Оказавшись внутри этой функции, учитывая объект, на котором находится свойство, и связанное с PropertyInfo, получите значение свойства, приведите его к IEnumerable (при условии, что это возможно), а затем выполните итерацию по каждому дочернему элементу и вызовите ReflectObject(...) на ребенка с переменной count.

Ответы [ 4 ]

11 голосов
/ 10 мая 2010

Когда вы делаете as IEnumerable и переменная не равна нулю, вы знаете, что она реализует интерфейс IEnumerable.

Вам не нужен код:

Type t = p.PropertyType;
//if (t.IsAssignableFrom(typeof(IEnumerable)))
if (t.IsSubclassOf(typeof(IEnumerable)))
{

Этого будет достаточно:

public void ReflectList(object o, PropertyInfo p, ReflectedListAttribute rla)
{
    IEnumerable e = p.GetValue(o, null) as IEnumerable;

    int count = 0;
    if (e != null)
    {
        foreach (object lo in e)
        {
            if (count >= rla.MaxRows)
                break;
            ReflectObject(lo, count);
            count++;
        }
    }
}
4 голосов
/ 10 мая 2010

С MSDN

Метод IsSubclassOf не может быть использован определить, есть ли интерфейс происходит из другого интерфейса, или реализует ли класс интерфейс Для этой цели используйте метод GetInterface

Также ваша реализация IsAssignableFrom неверна, вы должны использовать ее следующим образом:

typeof(IEnumerable).IsAssignableFrom(t)

Это должно вернуть true, если IEnumerable реализован t ..

3 голосов
/ 10 мая 2010

Зачем вам вообще if-оператор?

Вы уже сделали var e = ... as IEnumerable, а затем просто проверьте, не является ли оно нулевым.

Разве этого не достаточно?

1 голос
/ 10 мая 2010

Эти работы. :)

A List расширен Collection. Итак, тесты для них разные. A Dictionary имеет два внутренних контейнера. Отсюда один тест на одно и то же.

public static bool IsList(object obj)
{
    System.Collections.IList list = obj as System.Collections.IList;
    return list != null;
}

public static bool IsCollection(object obj)
{
    System.Collections.ICollection coll = obj as System.Collections.ICollection;
    return coll != null;
}

public static bool IsDictionary(object obj)
{
    System.Collections.IDictionary dictionary = obj as System.Collections.IDictionary;
    return dictionary != null;
}



Пример использования -

if (IsDictionary(fieldObject)) //key-value type collection?
{
    System.Collections.IDictionary dictionary = fieldObject as System.Collections.IDictionary;
    foreach (object _ob in dictionary.Values)
    {
        //do work
    }
    // dictionary.Clear();
}
else //normal collection
{
    if (IsCollection(fieldObject))
    {
        System.Collections.ICollection coll = fieldObject as System.Collections.ICollection;
        foreach (object _ob in coll)
        {
            //do work
        }

        if (IsList(fieldObject))
        {
            //System.Collections.IList list = fieldObject as System.Collections.IList;
            //list.Clear(); // <--- List's function, not Collection's.
        }
    }
}
...