1

I am trying to get all the ObservableCollection properties of an object using reflection. e.g. I have a Person class that has ObservableCollecton and ObservableCollection both the PhoneModel and AddressModel are inheriting from ModelBaseclass. Now I have the following function that is trying to pick all the ObservableCollection properties.

/// <summary>
/// Get all the oversablecollection properties from the object
/// </summary>
/// <typeparam name="T">type to search for</typeparam>
/// <param name="model">object to return properties for</param>
public IList<ObservableCollection<T>> GetObservableCollections<T>(object model)
{
    var type = model.GetType();
    var result = new List<ObservableCollection<T>>();
    foreach (var prop in type.GetProperties())
    {
        if (prop.PropertyType.IsAssignableFrom(typeof(ObservableCollection<T>)))
        {
            var get = prop.GetGetMethod();
            if (!get.IsStatic && get.GetParameters().Length == 0) // skip indexed & static
            {
                var collection = (ObservableCollection<T>)get.Invoke(model, null);
                if (collection != null) 
                    result.Add(collection);
            }
        }
    }

    return result;
}

This works:

[TestMethod]
public void GetObservableCollections_HasOnePublicProperty_Return1()
{
    var personWithPhones = GetValidPersonAndPhonesModel();
    var collection = GetObservableCollections<PhoneModel>(personWithPhones);

    Assert.IsTrue(collection.Count()==1);
}

I want this to work e.g find not for specific model but for ModelBase e.g I want all ObservableCollectionProperties both for address and phone

[TestMethod]
public void GetObservableCollections_HasOnePublicProperty_Return1()
{
    var personWithPhones = GetValidPersonAndPhonesModel();
    var collection = GetObservableCollections<ModelBase>(personWithPhones);

    Assert.IsTrue(collection.Count()==2);
}

The above doesn't return anything.

Any suggestions please?

===> This is the updated code after Peter's suggestion but there is some casting error:

            public static IList<ObservableCollection<T>> GetObservableCollections<T>(object obj)
    {
        var type = obj.GetType();

        IList<object> list = new List<object>();
        IList<ObservableCollection<T>> result = new List<ObservableCollection<T>>();
        foreach (var prop in type.GetProperties().Where(p=> p.PropertyType.IsGenericType))
        {
            var unclosedTyped = prop.PropertyType.GetGenericTypeDefinition();
            if (unclosedTyped == typeof(ObservableCollection<>))
            {
                // you have an ObservableCollection<> property
                var elementType = prop.PropertyType.GetGenericArguments().First();
                if (typeof(ModelBase).IsAssignableFrom(elementType))
                {
                    // you have indeed an ObservableCollection property 
                    // with elements that inherit `ModelBase`
                    var get = prop.GetGetMethod();
                    if (!get.IsStatic && get.GetParameters().Length == 0) // skip indexed & static
                    {
                        var collection = get.Invoke(obj, null);
                        if (collection != null)
                        {
                            //list.Add(collection); // This works
                            result.Add((ObservableCollection<T>) collection);
                        }
                    }
                }
            }
        }

        return list;
}
user1829319
  • 691
  • 1
  • 8
  • 22

1 Answers1

2

Instead of looking at the closed generic type, you can look for the unclosed type of ObservableCollection<>. Something like this:

var unclosedTyped = prop.PropertyType.GetGenericTypeDefinition();
if (unclosedTyped == typeof(ObservableCollection<>))
{
    // you have an ObservableCollection<> property
}

To further inspect the collection element type:

var elementType = prop.PropertyType.GetGenericArguments().First();
if (typeof(ModelBase).IsAssignableFrom(elementType))
{
   // you have indeed an ObservableCollection property 
   // with elements that inherit `ModelBase`
}
Peter Lillevold
  • 33,668
  • 7
  • 97
  • 131
  • Hi Peter, Thanks for your reply. This seems to be resolving that issue however I get an InvalidCastException when trying to cast the prop to ObservableCollection e.g. this line -> var collection = (ObservableCollection)get.Invoke(model, null); ..... I just wonder of this method will work at all? – user1829319 Nov 12 '14 at 10:03
  • Hm, are you on .NET 3.5 ? Check out this thread: http://stackoverflow.com/questions/1198751/how-can-i-cast-into-a-observablecollectionobject – Peter Lillevold Nov 12 '14 at 10:30
  • No I am in .Net 4.5. .... I can cast as Object that works fine... But I don't want that I guess ... – user1829319 Nov 12 '14 at 10:39