mfidemraizer / trackerdog

Generic object change tracker for .NET Framework and .NET Standard-compliant platforms like .NET Core and Xamarin!
http://mfidemraizer.github.io/trackerdog
Apache License 2.0
97 stars 10 forks source link

metadata question #35

Closed johnamcruz closed 7 years ago

johnamcruz commented 7 years ago

How do i compare the metadata from GetTrackableTypes() with the changeTracker.ChangedProperties? I am trying to get the full path of a property starting from A (i.e. A.B.C.Description).

var patch = new JsonPatchDocument<TModel>();
                var changeTracker = this.GetChangeTracker();
                var metadata = ChangeTrackingConfig.Value.GetTrackableType(typeof(TModel));
                foreach (var changedProperty in changeTracker.ChangedProperties)
                {
                    var property =
                        metadata.ObjectPaths.FirstOrDefault(t => t.Property.Name == changedProperty.PropertyName);
                    if (property != null)
                    {
                        patch.Operations.Add(new Operation<TModel>("replace",
                            $"/{property.Path.ToLower().Replace(".", "/")}",
                            null,
                            changedProperty.CurrentValue));
                    }

                }
                return patch;
mfidemraizer commented 7 years ago

I'll answer you this tonight!

mfidemraizer commented 7 years ago

Sorry, I couldn't give a check to your issue today. I'll try again tomorrow!

mfidemraizer commented 7 years ago

@johnamcruz Hey, I've checked your concern/issue.

If I'm not mistaken, you want to get the full path of a given property of TModel.

IObjectPropertyInfo implementations (those that gives ITrackableType.ObjectPaths property) own a property called Property. It's the PropertyInfo of a trackable property within the object graph starting in your case from TModel.

First of all, you should avoid comparing PropertyInfo.Name, because there could be more than a property with the same name in the object graph and you would get the first which may or may not be the property that has changed.

Therefore, I understand that you're looking for something like this:

var changedPropertyPath = metadata.ObjectPaths.SingleOrDefault(t => t.Property == changedProperty);

IObjectPropertyInfo.PathParts is a collection where the last item is the trackable property. Thus, PathParts gives you the path in order.

Is this what you're looking for?

johnamcruz commented 7 years ago

yup that helps a lot. Thank you @mfidemraizer

mfidemraizer commented 7 years ago

@johnamcruz Nice!

I need to stay honest: I had to run the tests and remember how it worked ;D Feel free to open new issues if you've any other question or problem.

johnamcruz commented 7 years ago

Hey @mfidemraizer

I dont think IObjectPropertyChangeTracking exposes the property field so i cant do

var property = metadata.ObjectPaths.SingleOrDefault(t => t.Property == changedProperty.Property);

mfidemraizer commented 7 years ago

@johnamcruz Oops! Sorry. You need to cast to IDeclaredObjectPropertyChangeTracking which will provide access to the PropertyInfo instance.

Since TrackerDog supports dynamic objects which won't declare their properties (see DynamicObject on MSDN), the most basic interface is IObjectPropertyChangeTracking, and regular objects instantiated from classes generate IDeclaredObjectPropertyChangeTracking implementation instances to track property changes.

Alter your foreach as follows:

foreach (var changedProperty in changeTracker.ChangedProperties.OfType<IDeclaredObjectPropertyChangeTracking>())
{
}