tags:

views:

62

answers:

1

I have the following method which returns true when a PropertyInfo instance references an object that is a collection of IDataExtractor objects:

    private bool IsCollectionOfIDataExtractors( PropertyInfo propInfo )
    {
        var result = false;

        var extractors = propInfo.GetValue(dataExtractor, null);

        if (typeof ( ICollection ).IsAssignableFrom(extractors.GetType() ) ||
            typeof ( ICollection<> ).IsAssignableFrom(extractors.GetType() ) )
        {

            IEnumerator extractor = ((ICollection)extractors).GetEnumerator();

            extractor.MoveNext();

            if (typeof ( IDataExtractor ).IsAssignableFrom(
                extractor.Current.GetType()) )
            {
                result = true;
            }
        }

        return result;
    }

When thinking about this method I searched through StackOverflow and found the following related item http://stackoverflow.com/questions/104603/accessing-a-collection-through-reflection/549212#549212 . That got me half way there.

After some testing it looks like this works, but I'm not 100% convinced. I'm working up beefier tests.

I'm curious though, is there a better way to implement this method? I don't really like the cast statement,

IEnumerator extractor = ((ICollection)extractors).GetEnumerator();
+1  A: 
var extractors = propInfo.GetValue(dataExtractor, null);
var asEnumerable = extractors as IEnumerable;

if (asEnumerable != null)
{
    var enumerator = asEnumerable.GetEnumerator();
    enumerator.MoveNext();

    if (enumerator.Current != null)
        return enumerator.Current is IDataExtractor;
}

return false;
Toby
It occurred to me as I was writing this that if the collection is empty, you'll have a harder time determining its member types, *and* your original code will throw a `NullReferenceException` at `extractor.Current.GetType()`.
Toby
The return with asCollection[0] won't compile, can't apply indexing to an expression of type ICollection. Replaced with: `var enumerator = asCollection.GetEnumerator();` `enumerator.MoveNext();` `return enumerator.Current is IDataExtractor;`
Martin Jasper
Thanks, this reduced the size of my code and made it easier to understand. Thank you Toby.
Martin Jasper
Just be aware that not all objects that implement `ICollection<T>` will necessarily implement `ICollection`. The same is true of `IList<T>` vs. `IList`.
Dan Bryant
I've rewritten using IEnumerable instead of ICollection since both ICollection and ICollection<> implement it.
Martin Jasper
@Dan: D'oh, you're right. I'm so used to seeing them implemented side-by-side that in my head the `ICollection` was an "inherited" interface.
Toby
@Martin: I've rewritten my code to use IEnumerable, as well, thanks.
Toby