views:

285

answers:

3

I am trying to derive the type of an object at runtime. Specifically I need to know two things whether it implements ICollection or IDto. Currently my only solution I have been able to find is this:

   private static bool IsACollection(PropertyDescriptor descriptor)
    {
        bool isCollection = false;

        foreach (Type type in descriptor.PropertyType.GetInterfaces())
        {
            if (type.IsGenericType)
            {
                if (type.GetGenericTypeDefinition() == typeof(ICollection<>))
                {
                    isCollection = true;
                    break;
                }
            }
            else
            {
                if (type == typeof(ICollection))
                {
                    isCollection = true;
                    break;
                }
            }
        }


        return isCollection;
    }

    private static bool IsADto(PropertyDescriptor descriptor)
    {
        bool isDto = false;

        foreach (Type type in descriptor.PropertyType.GetInterfaces())
        {
            if (type == typeof(IDto))
            {
                isDto = true;
                break;
            }
        }          
        return isDto;
    }

However I am convinced there has to be a better way than this. I have tried comparing in a normal fashion such as:

if(descriptor.PropertyType == typeof(ICollection<>))

However, this fails when using reflection yet when not using reflection it works fine.

I don't want to iterate through the interfaces for every field of my entity. Could someone shed some light on another method in which to do this? Yes, I am prematurely optimizing, but it looks ugly too so please humor me.

Caveats:

  1. It could or could not be generic, such as IList<> or just ArrayList thus why I am looking for ICollection or ICollection<>. So I assume I should use IsGenericType in an if statement to know whether to test using ICollection<> or not.

Thanks in advance!

+2  A: 

Does type.IsAssignable help in this case?

EDIT: Sorry, it should have been Type.IsAssignableFrom

shahkalpesh
Unfortunately no. When I check property.PropertyType.IsAssignableFrom(ICollection<>) and the type is an IList<> it still fails. Thank you though.
joshlrogers
A: 

You can check by casting directly to the desired type:

foo = (desiredtype) myobject;

But this will throw an exception if the cast is not possible.

Fortunately, you can us the as operator:

foo = myobject as desiredtype;

which won't throw an exception, and will just return null if the cast is impossible (so you can check for null to see if the cast failed. Also, as might only be in C#3, not sure,)

CrazyJugglerDrummer
This unfortunately does not work in my case because I do not have the object I only have the type of the object. Thank you though.
joshlrogers
+7  A: 

This:

type == typeof(ICollection)

will check if the type of property is exactly ICollection. That is, it will return true for:

public ICollection<int> x { get; set; }

but not for:

public List<int> x { get; set; }

If you want to check if the type of property is, or is derived from, ICollection, the simplest way is to use Type.IsAssignableFrom:

typeof(ICollection).IsAssignableFrom(type)

and the same goes for generic:

typeof(ICollection<>).IsAssignableFrom(type.GetGenericTypeDefinition())
Pavel Minaev
Actually he is going through the entire hierarchy. Additionally, ICollection<> does not implement ICollection directly.
Guvante
This did it, I had the order of these commands reversed! I was doing typeof(IList<>).IsAssignableFrom(typeof(ICollection<>). Thank you very much!
joshlrogers