mardi 7 avril 2020

How to cast an object I got via reflection into ObservableCollection

I'm trying to learn reflection so I'm writing an extension method on ObservableCollection<T> (where T : IChangeTracking) that calls AcceptChanges() on all elements of the collection but also recursively on all properties of objects in the collection that implement IChangeTracking, if those properties are also ObservableCollections.

This is what I have so far:

    /// <summary>
    /// Calls IChangeTracking.AcceptChanges() on all properties of all items in a collection that implement IChangeTracking interface.
    /// </summary>
    internal static void AcceptChangesWithChildren<T>(this ObservableCollection<T> collection) where T : IChangeTracking
    {
        // Calls IChangeTracking.AcceptChanges() on all items in a collection.
        collection.AcceptChanges();

        foreach (T item in collection)
        {
            PropertyInfo[] properties = item.GetType().GetProperties();

            foreach (PropertyInfo property in properties)
            {
                // regular properties that implement IChangeTracking
                if (typeof(IChangeTracking).IsAssignableFrom(property.PropertyType))
                {
                    property.PropertyType.GetMethod("AcceptChanges").Invoke(property, null);
                }

                // Collection of properties that implement IChangeTracking
                if (property.PropertyType.GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollection<>)) is Type itemsCollectionType)
                {
                    if (itemsCollectionType.GetGenericArguments().FirstOrDefault(i => typeof(IChangeTracking).IsAssignableFrom(i)) is Type changeTrackingType)
                    {
                        object changeTrackingObject = property.GetValue(item, null);

                        if (changeTrackingObject is IEnumerable<IChangeTracking> changeTrackingEnumerable)
                        {
                            changeTrackingEnumerable.Where(e => e.IsChanged).ForEach(e => e.AcceptChanges());
                        }
                    }
                }
            }
        }
    }

I have a problem in the last if statement. When I debug, changeTrackingObject is of type object{System.Collections.ObjectModel.ObservableCollection<SomeClassThatImplementsIChangeTracking>}.

The only thing I was able to cast it into was IEnumberable<IChangeTracking>, if I try to do ObservableObject<IChangeTracking> the check in if block evaluates to false. Is there a way to cast/unbox the changeTrackingObject as ObservableCollection so I can call AcceptChangesWithChildren<T>() Recursively?





Aucun commentaire:

Enregistrer un commentaire