开发者

IEnumerable<T> and reflection

开发者 https://www.devze.com 2022-12-29 23:20 出处:网络
Background Working in .NET 2.0 Here, reflecting lists in general. I was originally using t.IsAssignableFrom(typeof(IEnumerable)) to detect if a Property I was traversing supported the IEnumerable Int

Background

Working in .NET 2.0 Here, reflecting lists in general. I was originally using t.IsAssignableFrom(typeof(IEnumerable)) to detect if a Property I was traversing supported the IEnumerable Interface. (And thus I could cast the object to it safely)

However this code was not evaluating to True when the object is a BindingList<T>.

Next

I tried to use t.IsSubclassOf开发者_开发知识库(typeof(IEnumerable)) and didn't have any luck either.

Code

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

The Intent

I want to basically tag lists i want to reflect through with the ReflectedListAttribute and call this function on the properties that has it. (Already Working)

Once inside this function, given the object the property resides on, and the PropertyInfo related, get the value of the property, cast it to an IEnumerable (assuming it's possible) and then iterate through each child and call ReflectObject(...) on the child with the count variable.


When you do the as IEnumerable and the variable is not null you know that it does implement IEnumerable interface.

You don´t need the code:

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

This would be enough:

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


From MSDN

The IsSubclassOf method cannot be used to determine whether an interface derives from another interface, or whether a class implements an interface Use the GetInterface method for that purpose

Also your implementation of IsAssignableFrom is wrong, you should use it like this:

typeof(IEnumerable).IsAssignableFrom(t)

This should return true if IEnumerable is implemented by t..


Why do you the if-statement at all?

You already did a var e = ... as IEnumerable and afterwards just check if is not null.

Isn't that enough?


These work. :)

A List is extended Collection. So, the tests are different for them. A Dictionary has got two internal containers. Hence one test for the same.

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



Usage example -

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.
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号