/// <summary> /// Clones the given <see cref="System.Collections.IEnumerable"/> concrete implementation /// </summary> /// <param name="enumerable">The <see cref="System.Collections.IEnumerable"/> to clone</param> /// <param name="configuration">Configuration to use to determine how to clone the whole enumerable</param> /// <returns>The cloned enumerable</returns> internal static IEnumerable CloneEnumerable(this IEnumerable enumerable, IObjectChangeTrackingConfiguration configuration) { Contract.Requires(() => enumerable != null, "Given enumerable must be a non-null reference"); Type collectionType = configuration.Collections.GetImplementation(enumerable.GetType()).Value.Type; Type collectionItemType = enumerable.GetCollectionItemType(); List <Type> collectionTypeArguments = new List <Type>(); if (collectionItemType.GetTypeInfo().IsGenericType&& collectionItemType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)) { collectionTypeArguments.AddRange(collectionItemType.GenericTypeArguments); } else { collectionTypeArguments.Add(enumerable.GetCollectionItemType()); } IEnumerable collectionClone = (IEnumerable)collectionType .CreateInstanceWithGenericArgs(null, collectionTypeArguments.ToArray()); Type collectionInterface = collectionClone.GetType() .GetInterfaces() .Single(t => t.GetTypeInfo().IsGenericType&& t.GetGenericTypeDefinition() == typeof(ICollection <>)); MethodInfo addMethod = collectionInterface.GetMethod("Add", BindingFlags.Instance | BindingFlags.Public); foreach (object item in enumerable) { addMethod.Invoke(collectionClone, new[] { item }); } return(collectionClone); }
public static void Init(TestContext context) { Configuration = ObjectChangeTracking.CreateConfiguration() .TrackThisType <A>() .TrackThisType <TestDynamicObject>(); TrackableObjectFactory = Configuration.CreateTrackableObjectFactory(); }
public static void Init(TestContext context) { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.TrackThisType <IWhatever>(); TrackableObjectFactory = config.CreateTrackableObjectFactory(); }
public void Initialize() { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.TrackThisTypeRecursive <Class0>(); _trackableObjectFactory = config.CreateTrackableObjectFactory(); }
/// <summary> /// Default constructor /// </summary> /// <param name="targetObject">The object to track its changes</param> public ObjectChangeTracker(IObjectChangeTrackingConfiguration configuration, ITrackableObjectFactoryInternal trackableObjectFactory, object targetObject) { Contract.Requires(() => targetObject != null); Configuration = configuration; TrackableObjectFactory = trackableObjectFactory; _targetObject = targetObject; _targetObjectType = targetObject.GetType(); }
public ObjectPropertyChangeTracking(IObjectChangeTrackingConfiguration configuration, ITrackableObjectFactoryInternal trackableObjectFactory, ObjectChangeTracker tracker, object targetObject, string propertyName, object currentValue) { Configuration = configuration; TrackableObjectFactory = trackableObjectFactory; _tracker = tracker; _targetObject = targetObject; PropertyName = propertyName; OldValue = currentValue; CurrentValue = currentValue; }
public DeclaredObjectPropertyChangeTracking(IObjectChangeTrackingConfiguration configuration, ITrackableObjectFactoryInternal trackableObjectFactory, ObjectChangeTracker tracker, object targetObject, PropertyInfo ownerProperty, PropertyInfo property, object currentValue) { Configuration = configuration; TrackableObjectFactory = trackableObjectFactory; Tracker = tracker; TargetObject = targetObject; Property = property; OldValue = currentValue; CurrentValue = currentValue; }
public TrackableType(IObjectChangeTrackingConfiguration configuration, Type type) { //Contract.Requires(type != null, "Give type reference must be non-null"); Contract.Assert((type.IsClass && !type.IsSealed) || type.IsInterface, $"Given type '{type.AssemblyQualifiedName}' must be either a non-sealed class or an interface"); _type = type; _objectPaths = new Lazy <IImmutableSet <IObjectPropertyInfo> > ( () => Type.BuildAllPropertyPaths(p => configuration.CanTrackType(p.DeclaringType)) .Cast <IObjectPropertyInfo>() .ToImmutableHashSet() ); }
public void CanConfigureAbstractClass() { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.TrackTypesFromAssembly(typeof(ConfigurationTest).GetTypeInfo().Assembly, searchSettings: new TypeSearchSettings { Mode = TypeSearchMode.AttributeConfigurationOnly, /*Filter = t => t == typeof(AbstractClass) || t == typeof(DerivesAbstractClass),*/ Recursive = true }); ITrackableObjectFactory factory = config.CreateTrackableObjectFactory(); var x = factory.CreateFrom(new DerivesAbstractClass()); }
public void ConfiguresClassWithAllPropertiesExceptingNonTrackable() { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.TrackTypesFromAssembly(typeof(ConfigurationTest).GetTypeInfo().Assembly, searchSettings: new TypeSearchSettings { Mode = TypeSearchMode.AttributeConfigurationOnly, Filter = t => t == typeof(TwoPropertiesOneTrackable) }); ITrackableType trackableType = config.TrackableTypes.Single(); Assert.AreEqual(1, trackableType.IncludedProperties.Count); Assert.AreEqual("Text", trackableType.IncludedProperties.Single().Name); }
public void CanConfigureClassWithMultipleConstructors() { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.TrackTypesFromAssembly(typeof(ConfigurationTest).GetTypeInfo().Assembly, searchSettings: new TypeSearchSettings { Mode = TypeSearchMode.AttributeConfigurationOnly, Filter = t => t == typeof(WithMultipleConstructors) }); ITrackableObjectFactory factory = config.CreateTrackableObjectFactory(); WithMultipleConstructors instance = factory.CreateFrom(new WithMultipleConstructors()); Assert.IsNotNull(instance); }
public void ConfiguresClassWithAllProperties() { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.TrackTypesFromAssembly(typeof(ConfigurationTest).GetTypeInfo().Assembly, searchSettings: new TypeSearchSettings { Mode = TypeSearchMode.AttributeConfigurationOnly, Filter = t => t == typeof(AllProperties) }); ITrackableType trackableType = config.TrackableTypes.Single(); Assert.AreEqual(2, trackableType.IncludedProperties.Count); Assert.IsTrue(trackableType.IncludedProperties.Any(p => p.Name == "Text")); Assert.IsTrue(trackableType.IncludedProperties.Any(p => p.Name == "Text2")); }
public static void Init(TestContext context) { Configuration = ObjectChangeTracking.CreateConfiguration() .TrackThisType <A>(t => t.IncludeProperty(a => a.Items)) .TrackThisType <B>(t => t.IncludeProperty(b => b.Dogs)) .TrackThisType <C>(t => t.IncludeProperty(c => c.Dogs)) .TrackThisType <Dog>(t => t.IncludeProperty(d => d.Name)) .TrackThisType <D>() .TrackThisType <E>(t => t.IncludeProperty(e => e.Dictionary)) .TrackThisType <F>(t => t.IncludeProperty(f => f.ListOfF)) .TrackThisType <G>(t => t.IncludeProperty(g => g.Buffer)) .TrackThisType <WhateverBase>(t => t.IncludeProperty(w => w.List2)) .TrackThisType <WhateverParent>(t => t.IncludeProperty(w => w.List)); TrackableObjectFactory = Configuration.CreateTrackableObjectFactory(); }
public void CanConfigureWithNestedTypes() { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.TrackTypesFromAssembly(typeof(ConfigurationTest).GetTypeInfo().Assembly, searchSettings: new TypeSearchSettings { Mode = TypeSearchMode.AttributeConfigurationOnly, Filter = t => t == typeof(ClassWithNestedEnum) || t == typeof(DerivedClassWithNestedEnum) }); ITrackableObjectFactory factory = config.CreateTrackableObjectFactory(); DerivedClassWithNestedEnum instance = factory.CreateOf <DerivedClassWithNestedEnum>(); Assert.IsNotNull(instance); }
/// <summary> /// Iterates the given enumerable and returns an instance of given target collection type configured implementation /// where each item will be also converted to untracked objects. /// </summary> /// <param name="enumerable">The whole enumerable to untrack</param> /// <param name="targetCollectionType">The whole target collection type. This type should be a supported trackable collection type</param> /// <returns>A copy of source enumerable turned into an untracked collection</returns> public static IEnumerable ToUntrackedEnumerable(this IEnumerable enumerable, Type targetCollectionType) { Contract.Requires(() => targetCollectionType != null, "Target collection type cannot be a non-null reference"); if (enumerable != null) { Type collectionItemType = enumerable.GetCollectionItemType(); List <Type> collectionTypeArguments = new List <Type>(); if (collectionItemType.GetTypeInfo().IsGenericType&& collectionItemType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)) { collectionTypeArguments.AddRange(collectionItemType.GenericTypeArguments); } else { collectionTypeArguments.Add(enumerable.GetCollectionItemType()); } IObjectChangeTrackingConfiguration configuration = ((IChangeTrackableCollection)enumerable).GetChangeTrackingContext().Configuration; IEnumerable enumerableCopy = (IEnumerable)configuration.Collections.GetImplementation(targetCollectionType) .Value.Type.CreateInstanceWithGenericArgs(null, collectionTypeArguments.ToArray()); Type collectionInterface = enumerableCopy.GetType() .GetInterfaces() .Single(t => t.GetTypeInfo().IsGenericType&& t.GetGenericTypeDefinition() == typeof(ICollection <>)); MethodInfo addMethod = collectionInterface.GetMethod("Add", BindingFlags.Instance | BindingFlags.Public); Contract.Assert(() => addMethod != null); foreach (object item in enumerable) { addMethod.Invoke(enumerableCopy, new[] { item.ToUntypedUntracked() }); } return(enumerableCopy); } else { return(null); } }
public void ConfiguresWithAttributesOnly() { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.TrackTypesFromAssembly(typeof(ConfigurationTest).Assembly, searchSettings: new TypeSearchSettings { Mode = TypeSearchMode.AttributeConfigurationOnly, Filter = t => t.ReflectedType == typeof(ConfigurationTest) }); IList <Type> trackables = config.TrackableTypes.Select(t => t.Type).ToList(); Assert.IsTrue(config.TrackableTypes.Count > 0); Assert.IsTrue(trackables.Contains(typeof(AllProperties))); Assert.IsTrue(trackables.Contains(typeof(AllPropertiesExceptingNonTrackable))); Assert.IsTrue(trackables.Contains(typeof(TwoPropertiesOneTrackable))); Assert.IsFalse(trackables.Contains(typeof(NoAttributes))); }
public void CanConfigureClassWithReadOnlyProperties() { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.TrackTypesFromAssembly(typeof(ConfigurationTest).GetTypeInfo().Assembly, searchSettings: new TypeSearchSettings { Mode = TypeSearchMode.AttributeConfigurationOnly, Filter = t => t == typeof(ClassWithReadOnlyProperties) }); ITrackableObjectFactory factory = config.CreateTrackableObjectFactory(); ClassWithReadOnlyProperties instance = factory.CreateFrom(new ClassWithReadOnlyProperties()); instance.Text = "hey"; IObjectChangeTracker tracker = instance.GetChangeTracker(); Assert.AreEqual(1, tracker.ChangedProperties.Count); Assert.AreEqual(1, ((ObjectChangeTracker)tracker).PropertyTrackings.Count); }
public void CanConfigureNonTrackablePropertiesFromBaseClasses() { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.TrackTypesFromAssembly(typeof(ConfigurationTest).GetTypeInfo().Assembly, searchSettings: new TypeSearchSettings { Mode = TypeSearchMode.AttributeConfigurationOnly, Recursive = true, Filter = t => { return(t.DeclaringType == typeof(ConfigurationTest)); } }); ITrackableObjectFactory trackableObjectFactory = config.CreateTrackableObjectFactory(); DerivedClassOfBaseClassWithNonTrackableProperty obj = trackableObjectFactory.CreateOf <DerivedClassOfBaseClassWithNonTrackableProperty>(); IObjectChangeTracker changeTracker = obj.GetChangeTracker(); Assert.AreEqual(1, changeTracker.Count()); Assert.IsTrue(changeTracker.First().PropertyName == "Text2"); }
// TODO: Remove? /// <summary> /// Turns all objects into change-trackable ones found in the given sequence. /// </summary> /// <typeparam name="T">The type of objects</typeparam> /// <param name="enumerable">The sequence of objects to turn into change-trackable ones</param> /// <param name="parentObjectProperty">The collection property representing the association to some object</param> /// <param name="parentObject">The parent object that owns the association of the collection</param> /// <returns>The already converted objects into change-trackable ones</returns> public static IEnumerable <T> MakeAllTrackable <T>(this IEnumerable <T> enumerable, IObjectChangeTrackingConfiguration configuration, ITrackableObjectFactory trackableObjectFactory, PropertyInfo parentObjectProperty, IChangeTrackableObject parentObject) where T : class { Contract.Requires(() => enumerable != null, "Given enumerable must be a non-null reference to turn its objects into trackable ones"); Contract.Requires(() => parentObjectProperty != null, "A reference to property which holds the enumerable is mandatory"); Contract.Requires(() => parentObject != null, "The instance of the object where the property holding the enumerable is declared is mandatory"); Contract.Requires(() => parentObjectProperty.DeclaringType.GetActualTypeIfTrackable().IsAssignableFrom(parentObject.GetActualTypeIfTrackable()), "Given property holding the enumerable must be declared on the given parent object type"); if (enumerable.Count() > 0 && configuration.CanTrackType(enumerable.First().GetType())) { List <T> result = new List <T>(); foreach (T item in enumerable) { IChangeTrackableObject trackableObject = item as IChangeTrackableObject; if (trackableObject == null) { trackableObject = (IChangeTrackableObject)trackableObjectFactory.CreateFrom(item); trackableObject.PropertyChanged += (sender, e) => parentObject.RaisePropertyChanged(parentObject, parentObjectProperty.Name); } result.Add((T)trackableObject); } Contract.Assert(() => result.Count == enumerable.Count(), "New sequence with objects turned into trackable ones must match the count of source sequence"); return(result); } else { return(enumerable); } }
public TrackableType(IObjectChangeTrackingConfiguration configuration) : base(configuration, typeof(T)) { }
public ChangeTrackableObjectMixin(IObjectChangeTrackingConfiguration configuration, ITrackableObjectFactoryInternal trackableObjectFactory) { ChangeTrackingContext.Configuration = configuration; TrackableObjectFactory = trackableObjectFactory; }
public void CanReplaceCollectionChangeTrackingImplementation() { IObjectChangeTrackingConfiguration config = ObjectChangeTracking.CreateConfiguration(); config.Collections.AddOrUpdateImplementation <ICollection <string>, List <string>, DefaultCollectionChangeInterceptor <string> >(); }
public SimplePropertyInterceptionHook(IObjectChangeTrackingConfiguration configuration) { Configuration = configuration; }
public TrackableObjectFactoryInternal(IObjectChangeTrackingConfiguration configuration) { Configuration = configuration; }
public CollectionPropertyInterceptor(IObjectChangeTrackingConfiguration configuration, ITrackableObjectFactory trackableObjectFactory) { Configuration = configuration; TrackableObjectFactory = trackableObjectFactory; }
public AttributeConfigurationBuilder(IObjectChangeTrackingConfiguration config) { Configuration = config; }
public DynamicObjectInterceptor(IObjectChangeTrackingConfiguration configuration, ITrackableObjectFactory trackableObjectFactory) { Configuration = configuration; TrackableObjectFactory = trackableObjectFactory; }