From 6db9bb2466b3e8822caaa274237c481788ed3d36 Mon Sep 17 00:00:00 2001 From: Herman Schoenfeld Date: Tue, 18 Dec 2018 13:22:41 +1000 Subject: [PATCH 1/2] Generate all mappings in the order they were declared (long awaited feature). --- src/FluentNHibernate/Mapping/ClassMap.cs | 100 ++++--- .../Mapping/MappingProviderStore.cs | 221 ++++++++++++++-- src/FluentNHibernate/Mapping/SubclassMap.cs | 52 ++-- .../MappingModel/MappedMembers.cs | 247 +++++++----------- .../Utils/ObservableDictionary.cs | 225 ++++++++++++++++ 5 files changed, 620 insertions(+), 225 deletions(-) create mode 100644 src/FluentNHibernate/Utils/ObservableDictionary.cs diff --git a/src/FluentNHibernate/Mapping/ClassMap.cs b/src/FluentNHibernate/Mapping/ClassMap.cs index aa45671c2..d699c6ed3 100644 --- a/src/FluentNHibernate/Mapping/ClassMap.cs +++ b/src/FluentNHibernate/Mapping/ClassMap.cs @@ -618,56 +618,70 @@ ClassMapping IMappingProvider.GetClassMapping() mapping.Set(x => x.Type, Layer.Defaults, typeof(T)); mapping.Set(x => x.Name, Layer.Defaults, typeof(T).AssemblyQualifiedName); - foreach (var property in providers.Properties) - mapping.AddProperty(property.GetPropertyMapping()); - - foreach (var component in providers.Components) - mapping.AddComponent(component.GetComponentMapping()); - if (providers.Version != null) - mapping.Set(x => x.Version, Layer.Defaults, providers.Version.GetVersionMapping()); - - foreach (var oneToOne in providers.OneToOnes) - mapping.AddOneToOne(oneToOne.GetOneToOneMapping()); - - foreach (var collection in providers.Collections) - mapping.AddCollection(collection.GetCollectionMapping()); - - foreach (var reference in providers.References) - mapping.AddReference(reference.GetManyToOneMapping()); - - foreach (var any in providers.Anys) - mapping.AddAny(any.GetAnyMapping()); - - foreach (var subclass in providers.Subclasses.Values) - mapping.AddSubclass(subclass.GetSubclassMapping()); - - foreach (var join in providers.Joins) - mapping.AddJoin(join.GetJoinMapping()); - - if (providers.Discriminator != null) - mapping.Set(x => x.Discriminator, Layer.Defaults, providers.Discriminator.GetDiscriminatorMapping()); + mapping.Set(x => x.Version, Layer.Defaults, providers.Version.GetVersionMapping()); + + foreach (var provider in providers.OrderedProviders) { + var x = provider.Item2; + switch (provider.Item1) { + case MappingProviderStore.ProviderType.Property: + mapping.AddProperty(((IPropertyMappingProvider) x).GetPropertyMapping()); + break; + case MappingProviderStore.ProviderType.Component: + mapping.AddComponent(((IComponentMappingProvider) x).GetComponentMapping()); + break; + case MappingProviderStore.ProviderType.OneToOne: + mapping.AddOneToOne(((IOneToOneMappingProvider) x).GetOneToOneMapping()); + break; + case MappingProviderStore.ProviderType.Subclass: + mapping.AddSubclass(((ISubclassMappingProvider) x).GetSubclassMapping()); + break; + case MappingProviderStore.ProviderType.Collection: + mapping.AddCollection(((ICollectionMappingProvider) x).GetCollectionMapping()); + break; + case MappingProviderStore.ProviderType.ManyToOne: + mapping.AddReference(((IManyToOneMappingProvider) x).GetManyToOneMapping()); + break; + case MappingProviderStore.ProviderType.Any: + mapping.AddAny(((IAnyMappingProvider) x).GetAnyMapping()); + break; + case MappingProviderStore.ProviderType.Filter: + mapping.AddFilter(((IFilterMappingProvider) x).GetFilterMapping()); + break; + case MappingProviderStore.ProviderType.StoredProcedure: + mapping.AddStoredProcedure(((IStoredProcedureMappingProvider) x).GetStoredProcedureMapping()); + break; + case MappingProviderStore.ProviderType.Join: + mapping.AddJoin(((IJoinMappingProvider) x).GetJoinMapping()); + break; + case MappingProviderStore.ProviderType.Identity: + mapping.Set(y => y.Id, Layer.Defaults, ((IIdentityMappingProvider) x).GetIdentityMapping()); + break; + case MappingProviderStore.ProviderType.CompositeId: + mapping.Set(y => y.Id, Layer.Defaults, ((ICompositeIdMappingProvider) x).GetCompositeIdMapping()); + break; + case MappingProviderStore.ProviderType.NaturalId: + mapping.Set(y => y.NaturalId, Layer.Defaults, ((INaturalIdMappingProvider) x).GetNaturalIdMapping()); + break; + case MappingProviderStore.ProviderType.Version: + mapping.Set(y => y.Version, Layer.Defaults, ((IVersionMappingProvider) x).GetVersionMapping()); + break; + case MappingProviderStore.ProviderType.Discriminator: + mapping.Set(y => y.Discriminator, Layer.Defaults, ((IDiscriminatorMappingProvider) x).GetDiscriminatorMapping()); + break; + case MappingProviderStore.ProviderType.Tupilizer: + mapping.Set(y => y.Tuplizer, Layer.Defaults, (TuplizerMapping)x); + break; + default: + throw new Exception("Internal Error"); + } + } if (Cache.IsDirty) mapping.Set(x => x.Cache, Layer.Defaults, ((ICacheMappingProvider)Cache).GetCacheMapping()); - if (providers.Id != null) - mapping.Set(x => x.Id, Layer.Defaults, providers.Id.GetIdentityMapping()); - - if (providers.CompositeId != null) - mapping.Set(x => x.Id, Layer.Defaults, providers.CompositeId.GetCompositeIdMapping()); - - if (providers.NaturalId != null) - mapping.Set(x => x.NaturalId, Layer.Defaults, providers.NaturalId.GetNaturalIdMapping()); - mapping.Set(x => x.TableName, Layer.Defaults, GetDefaultTableName()); - foreach (var filter in providers.Filters) - mapping.AddFilter(filter.GetFilterMapping()); - - foreach (var storedProcedure in providers.StoredProcedures) - mapping.AddStoredProcedure(storedProcedure.GetStoredProcedureMapping()); - mapping.Set(x => x.Tuplizer, Layer.Defaults, providers.TuplizerMapping); return mapping; diff --git a/src/FluentNHibernate/Mapping/MappingProviderStore.cs b/src/FluentNHibernate/Mapping/MappingProviderStore.cs index 75d498e72..2e8d34518 100644 --- a/src/FluentNHibernate/Mapping/MappingProviderStore.cs +++ b/src/FluentNHibernate/Mapping/MappingProviderStore.cs @@ -1,42 +1,227 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Linq; using FluentNHibernate.Mapping.Providers; using FluentNHibernate.MappingModel; +using FluentNHibernate.Utils; namespace FluentNHibernate.Mapping { public class MappingProviderStore { + public enum ProviderType { + Property, + Component, + OneToOne, + Subclass, + Collection, + ManyToOne, + Any, + Filter, + StoredProcedure, + Join, + Identity, + CompositeId, + NaturalId, + Version, + Discriminator, + Tupilizer + } + public IList Properties { get; set; } public IList Components { get; set; } public IList OneToOnes { get; set; } - public Dictionary Subclasses { get; set; } + public IDictionary Subclasses { get; set; } public IList Collections { get; set; } public IList References { get; set; } public IList Anys { get; set; } public IList Filters { get; set; } public IList StoredProcedures { get; set; } public IList Joins { get; set; } + private IIdentityMappingProvider _id; + private ICompositeIdMappingProvider _compositeId; + private INaturalIdMappingProvider _naturalId; + private IVersionMappingProvider _version; + private IDiscriminatorMappingProvider _discriminator; + private TuplizerMapping _tuplizerMapping; + private IList> orderedProviders; + + + public IIdentityMappingProvider Id { + get { + return _id; + } + set { + ReplaceOrAddProvider(ProviderType.Identity, _id, value); + _id = value; + } + } + + public ICompositeIdMappingProvider CompositeId { + get { + return _compositeId; + } + set { + ReplaceOrAddProvider(ProviderType.CompositeId, _compositeId, value); + _compositeId = value; + } + } + + public INaturalIdMappingProvider NaturalId { + get { + return _naturalId; + } + set { + ReplaceOrAddProvider(ProviderType.NaturalId, _naturalId, value); + _naturalId = value; + } + } + + public IVersionMappingProvider Version { + get { + return _version; + } + set { + ReplaceOrAddProvider(ProviderType.Version, _version, value); + _version = value; + } + } + + public IDiscriminatorMappingProvider Discriminator { + get { + return _discriminator; + } + set { + ReplaceOrAddProvider(ProviderType.Discriminator, _discriminator, value); + _discriminator = value; + } + } - public IIdentityMappingProvider Id { get; set; } - public ICompositeIdMappingProvider CompositeId { get; set; } - public INaturalIdMappingProvider NaturalId { get; set; } - public IVersionMappingProvider Version { get; set; } - public IDiscriminatorMappingProvider Discriminator { get; set; } - public TuplizerMapping TuplizerMapping { get; set; } + public TuplizerMapping TuplizerMapping { + get { + return _tuplizerMapping; + } + set { + ReplaceOrAddProvider(ProviderType.Tupilizer, _tuplizerMapping, value); + _tuplizerMapping = value; + } + } public MappingProviderStore() - { - Properties = new List(); - Components = new List(); - OneToOnes = new List(); - Subclasses = new Dictionary(); - Collections = new List(); - References = new List(); - Anys = new List(); - Filters = new List(); - StoredProcedures = new List(); - Joins = new List(); + { + Properties = NewObservedList(); + Components = NewObservedList(); + OneToOnes = NewObservedList(); + Subclasses = NewObservedDictionary(); + Collections = NewObservedList(); + References = NewObservedList(); + Anys = NewObservedList(); + Filters = NewObservedList(); + StoredProcedures = NewObservedList(); + Joins = NewObservedList(); + orderedProviders = new List>(); + } + + public IEnumerable> OrderedProviders { + get { return orderedProviders.Select(x => x); } + } + + private IList NewObservedList() { + + ProviderType TypeSelector(object o) + { + if (ReferenceEquals(o, Properties)) { + return ProviderType.Property; + } else if (ReferenceEquals(o, Components)) { + return ProviderType.Component; + } else if (ReferenceEquals(o, OneToOnes)) { + return ProviderType.OneToOne; + } else if (ReferenceEquals(o, Collections)) { + return ProviderType.Collection; + } else if (ReferenceEquals(o, References)) { + return ProviderType.ManyToOne; + } else if (ReferenceEquals(o, Anys)) { + return ProviderType.Any; + } else if (ReferenceEquals(o, Filters)) { + return ProviderType.Filter; + } else if (ReferenceEquals(o, StoredProcedures)) { + return ProviderType.StoredProcedure; + } else if (ReferenceEquals(o, Joins)) { + return ProviderType.Join; + } + throw new Exception("Internal Error"); + } + + var observableList = new ObservableCollection(); + observableList.CollectionChanged += (sender, args) => { + var type = TypeSelector(sender); + switch (args.Action) { + case NotifyCollectionChangedAction.Add: + foreach (var newItem in args.NewItems) + orderedProviders.Add(Tuple.Create(type, newItem)); + break; + case NotifyCollectionChangedAction.Move: + throw new NotSupportedException(); + + case NotifyCollectionChangedAction.Remove: + foreach (var oldItem in args.OldItems) + orderedProviders.Remove(Tuple.Create(type, oldItem)); + break; + case NotifyCollectionChangedAction.Replace: + throw new NotSupportedException(); + case NotifyCollectionChangedAction.Reset: + foreach (var oldItem in args.OldItems) + orderedProviders.Remove(Tuple.Create(type, oldItem)); + break; + } + }; + return observableList; } + + private IDictionary NewObservedDictionary() { + var observedDictionary = new ObservableDictionary(); + observedDictionary.CollectionChanged += (sender, args) => { + switch (args.Action) { + case NotifyCollectionChangedAction.Add: + if (args.NewStartingIndex < ((IDictionary)sender).Count) { + //Inserting + for (var i = 0; i < args.NewItems.Count; i++) { + var newValue = (KeyValuePair)args.NewItems[i]; + orderedProviders.Insert(args.NewStartingIndex + i, Tuple.Create(ProviderType.Subclass, (object)newValue.Value)); + } + } else { + //Appending + foreach (KeyValuePair newItem in args.NewItems) { + orderedProviders.Add(Tuple.Create(ProviderType.Subclass, (object)newItem.Value)); + } + } + break; + case NotifyCollectionChangedAction.Move: + throw new NotSupportedException(); + case NotifyCollectionChangedAction.Remove: + foreach (KeyValuePair oldItem in args.OldItems) + orderedProviders.Remove(Tuple.Create(ProviderType.Subclass, (object)oldItem.Value)); + break; + case NotifyCollectionChangedAction.Replace: + throw new NotSupportedException(); + case NotifyCollectionChangedAction.Reset: + foreach (KeyValuePair oldItem in args.OldItems) + orderedProviders.Remove(Tuple.Create(ProviderType.Subclass, (object)oldItem.Value)); + break; + } + }; + return observedDictionary; + } + + private void ReplaceOrAddProvider(ProviderType type, object oldObj, object newObj) { + var index = orderedProviders.IndexOf(Tuple.Create(type, oldObj)); + var newObjTuple = Tuple.Create(type, newObj); + if (index > 0) + orderedProviders[index] = newObjTuple; + else + orderedProviders.Add(newObjTuple); + } } } \ No newline at end of file diff --git a/src/FluentNHibernate/Mapping/SubclassMap.cs b/src/FluentNHibernate/Mapping/SubclassMap.cs index 350912ebe..ee9e00bf1 100644 --- a/src/FluentNHibernate/Mapping/SubclassMap.cs +++ b/src/FluentNHibernate/Mapping/SubclassMap.cs @@ -309,23 +309,41 @@ SubclassMapping IIndeterminateSubclassMappingProvider.GetSubclassMapping(Subclas foreach (var join in joins) mapping.AddJoin(join); - foreach (var property in providers.Properties) - mapping.AddProperty(property.GetPropertyMapping()); - - foreach (var component in providers.Components) - mapping.AddComponent(component.GetComponentMapping()); - - foreach (var oneToOne in providers.OneToOnes) - mapping.AddOneToOne(oneToOne.GetOneToOneMapping()); - - foreach (var collection in providers.Collections) - mapping.AddCollection(collection.GetCollectionMapping()); - - foreach (var reference in providers.References) - mapping.AddReference(reference.GetManyToOneMapping()); - - foreach (var any in providers.Anys) - mapping.AddAny(any.GetAnyMapping()); + foreach (var provider in providers.OrderedProviders) { + var x = provider.Item2; + switch (provider.Item1) { + case MappingProviderStore.ProviderType.Property: + mapping.AddProperty(((IPropertyMappingProvider)x).GetPropertyMapping()); + break; + case MappingProviderStore.ProviderType.Component: + mapping.AddComponent(((IComponentMappingProvider)x).GetComponentMapping()); + break; + case MappingProviderStore.ProviderType.OneToOne: + mapping.AddOneToOne(((IOneToOneMappingProvider)x).GetOneToOneMapping()); + break; + case MappingProviderStore.ProviderType.Collection: + mapping.AddCollection(((ICollectionMappingProvider)x).GetCollectionMapping()); + break; + case MappingProviderStore.ProviderType.ManyToOne: + mapping.AddReference(((IManyToOneMappingProvider)x).GetManyToOneMapping()); + break; + case MappingProviderStore.ProviderType.Any: + mapping.AddAny(((IAnyMappingProvider)x).GetAnyMapping()); + break; + case MappingProviderStore.ProviderType.Subclass: + case MappingProviderStore.ProviderType.Filter: + case MappingProviderStore.ProviderType.StoredProcedure: + case MappingProviderStore.ProviderType.Join: + case MappingProviderStore.ProviderType.Identity: + case MappingProviderStore.ProviderType.CompositeId: + case MappingProviderStore.ProviderType.NaturalId: + case MappingProviderStore.ProviderType.Version: + case MappingProviderStore.ProviderType.Discriminator: + case MappingProviderStore.ProviderType.Tupilizer: + default: + throw new Exception("Internal Error"); + } + } return mapping.DeepClone(); } diff --git a/src/FluentNHibernate/MappingModel/MappedMembers.cs b/src/FluentNHibernate/MappingModel/MappedMembers.cs index cbd750515..97ead01ca 100644 --- a/src/FluentNHibernate/MappingModel/MappedMembers.cs +++ b/src/FluentNHibernate/MappingModel/MappedMembers.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; using FluentNHibernate.MappingModel.ClassBased; +using FluentNHibernate.Utils; using FluentNHibernate.Visitors; namespace FluentNHibernate.MappingModel @@ -8,211 +11,168 @@ namespace FluentNHibernate.MappingModel [Serializable] internal class MappedMembers : IMapping, IHasMappedMembers { - private readonly List properties; - private readonly List collections; - private readonly List references; - private readonly List components; - private readonly List oneToOnes; - private readonly List anys; - private readonly List joins; - private readonly List filters; - private readonly List storedProcedures; - - public MappedMembers() - { - properties = new List(); - collections = new List(); - references = new List(); - components = new List(); - oneToOnes = new List(); - anys = new List(); - joins = new List(); - filters = new List(); - storedProcedures = new List(); + public enum MappingType { + Property, + Collection, + ManyToOne, + IComponent, + OneToOne, + Any, + Join, + Filter, + StoredProcedure, } - public IEnumerable Properties - { - get { return properties; } - } + private readonly List> orderedMappings; - public IEnumerable Collections + public MappedMembers() { - get { return collections; } + orderedMappings = new List>(); } - public IEnumerable References - { - get { return references; } - } + public IEnumerable Properties => orderedMappings.Where(x => x.Item1 == MappingType.Property).Select(x => x.Item2).Cast(); - public IEnumerable Components - { - get { return components; } - } + public IEnumerable Collections => orderedMappings.Where(x => x.Item1 == MappingType.Collection).Select(x => x.Item2).Cast(); - public IEnumerable OneToOnes - { - get { return oneToOnes; } - } + public IEnumerable References => orderedMappings.Where(x => x.Item1 == MappingType.ManyToOne).Select(x => x.Item2).Cast(); - public IEnumerable Anys - { - get { return anys; } - } + public IEnumerable Components => orderedMappings.Where(x => x.Item1 == MappingType.IComponent).Select(x => x.Item2).Cast(); - public IEnumerable Joins - { - get { return joins; } - } + public IEnumerable OneToOnes => orderedMappings.Where(x => x.Item1 == MappingType.OneToOne).Select(x => x.Item2).Cast(); - public IEnumerable Filters - { - get { return filters; } - } + public IEnumerable Anys => orderedMappings.Where(x => x.Item1 == MappingType.Any).Select(x => x.Item2).Cast(); - public void AddOrReplaceFilter(FilterMapping mapping) - { - var filter = filters.Find(x => x.Name == mapping.Name); - if (filter != null) - filters.Remove(filter); - filters.Add(mapping); - } + public IEnumerable Joins => orderedMappings.Where(x => x.Item1 == MappingType.Join).Select(x => x.Item2).Cast(); + public IEnumerable Filters => orderedMappings.Where(x => x.Item1 == MappingType.Filter).Select(x => x.Item2).Cast(); - public IEnumerable StoredProcedures + public IEnumerable StoredProcedures => orderedMappings.Where(x => x.Item1 == MappingType.StoredProcedure).Select(x => x.Item2).Cast(); + + public void AddOrReplaceFilter(FilterMapping mapping) { - get { return storedProcedures; } + AddOrReplaceMapping(mapping, MappingType.Filter, x => x.Name == mapping.Name); } public void AddProperty(PropertyMapping property) { - if (properties.Exists(x => x.Name == property.Name)) + if (Properties.Any(x => x.Name == property.Name)) throw new InvalidOperationException("Tried to add property '" + property.Name + "' when already added."); - - properties.Add(property); + AddMapping(property, MappingType.Property); } public void AddOrReplaceProperty(PropertyMapping mapping) { - properties.RemoveAll(x => x.Name == mapping.Name); - properties.Add(mapping); + AddOrReplaceMapping(mapping, MappingType.Property, x => x.Name == mapping.Name); } public void AddCollection(Collections.CollectionMapping collection) { - if (collections.Exists(x => x.Name == collection.Name)) + if (Collections.Any(x => x.Name == collection.Name)) throw new InvalidOperationException("Tried to add collection '" + collection.Name + "' when already added."); - - collections.Add(collection); + AddMapping(collection, MappingType.Collection); } public void AddOrReplaceCollection(Collections.CollectionMapping mapping) { - collections.RemoveAll(x => x.Name == mapping.Name); - collections.Add(mapping); + AddOrReplaceMapping(mapping, MappingType.Collection, x => x.Name == mapping.Name); } public void AddReference(ManyToOneMapping manyToOne) { - if (references.Exists(x => x.Name == manyToOne.Name)) + if (References.Any(x => x.Name == manyToOne.Name)) throw new InvalidOperationException("Tried to add many-to-one '" + manyToOne.Name + "' when already added."); - - references.Add(manyToOne); + AddMapping(manyToOne, MappingType.ManyToOne); } public void AddOrReplaceReference(ManyToOneMapping manyToOne) { - references.RemoveAll(x => x.Name == manyToOne.Name); - references.Add(manyToOne); + AddOrReplaceMapping(manyToOne, MappingType.ManyToOne, x => x.Name == manyToOne.Name); } public void AddComponent(IComponentMapping componentMapping) { - if (components.Exists(x => x.Name == componentMapping.Name)) + if (Components.Any(x => x.Name == componentMapping.Name)) throw new InvalidOperationException("Tried to add component '" + componentMapping.Name + "' when already added."); - - components.Add(componentMapping); + AddMapping(componentMapping, MappingType.IComponent); } public void AddOrReplaceComponent(IComponentMapping componentMapping) { - components.RemoveAll(x => x.Name == componentMapping.Name); - components.Add(componentMapping); + AddOrReplaceMapping(componentMapping, MappingType.IComponent, x => x.Name == componentMapping.Name); } public void AddOneToOne(OneToOneMapping mapping) { - if (oneToOnes.Exists(x => x.Name == mapping.Name)) + if (OneToOnes.Any(x => x.Name == mapping.Name)) throw new InvalidOperationException("Tried to add one-to-one '" + mapping.Name + "' when already added."); - - oneToOnes.Add(mapping); + AddMapping(mapping, MappingType.OneToOne); } public void AddOrReplaceOneToOne(OneToOneMapping mapping) { - oneToOnes.RemoveAll(x => x.Name == mapping.Name); - oneToOnes.Add(mapping); + AddOrReplaceMapping(mapping, MappingType.OneToOne, x => x.Name == mapping.Name); } public void AddAny(AnyMapping mapping) { - if (anys.Exists(x => x.Name == mapping.Name)) + if (Anys.Any(x => x.Name == mapping.Name)) throw new InvalidOperationException("Tried to add any '" + mapping.Name + "' when already added."); - - anys.Add(mapping); + AddMapping(mapping, MappingType.Any); } public void AddOrReplaceAny(AnyMapping mapping) { - anys.RemoveAll(x => x.Name == mapping.Name); - anys.Add(mapping); + AddOrReplaceMapping(mapping, MappingType.Any, x => x.Name == mapping.Name); } public void AddJoin(JoinMapping mapping) { - if (joins.Exists(x => x.TableName == mapping.TableName)) + if (Joins.Any(x => x.TableName == mapping.TableName)) throw new InvalidOperationException("Tried to add join to table '" + mapping.TableName + "' when already added."); - - joins.Add(mapping); + AddMapping(mapping, MappingType.Join); } public void AddFilter(FilterMapping mapping) { - if (filters.Exists(x => x.Name == mapping.Name)) + if (Filters.Any(x => x.Name == mapping.Name)) throw new InvalidOperationException("Tried to add filter with name '" + mapping.Name + "' when already added."); - - filters.Add(mapping); + AddMapping(mapping, MappingType.Filter); } public virtual void AcceptVisitor(IMappingModelVisitor visitor) { - foreach (var collection in Collections) - visitor.Visit(collection); - - foreach (var property in Properties) - visitor.Visit(property); - - foreach (var reference in References) - visitor.Visit(reference); - - foreach (var component in Components) - visitor.Visit(component); - - foreach (var oneToOne in oneToOnes) - visitor.Visit(oneToOne); - - foreach (var any in anys) - visitor.Visit(any); - - foreach (var join in joins) - visitor.Visit(join); - - foreach (var filter in filters) - visitor.Visit(filter); - - foreach (var storedProcedure in storedProcedures) - visitor.Visit(storedProcedure); + foreach(var mapping in orderedMappings) + switch (mapping.Item1) { + case MappingType.Property: + visitor.Visit((PropertyMapping)mapping.Item2); + break; + case MappingType.Collection: + visitor.Visit((Collections.CollectionMapping)mapping.Item2); + break; + case MappingType.ManyToOne: + visitor.Visit((ManyToOneMapping)mapping.Item2); + break; + case MappingType.IComponent: + visitor.Visit((IComponentMapping)mapping.Item2); + break; + case MappingType.OneToOne: + visitor.Visit((OneToOneMapping)mapping.Item2); + break; + case MappingType.Any: + visitor.Visit((AnyMapping)mapping.Item2); + break; + case MappingType.Join: + visitor.Visit((JoinMapping)mapping.Item2); + break; + case MappingType.Filter: + visitor.Visit((FilterMapping)mapping.Item2); + break; + case MappingType.StoredProcedure: + visitor.Visit((StoredProcedureMapping)mapping.Item2); + break; + default: + throw new Exception("Internal Error: unsupported mapping type " + mapping.Item1); + } } public bool IsSpecified(string property) @@ -225,22 +185,14 @@ public void Set(string attribute, int layer, object value) public void AddStoredProcedure(StoredProcedureMapping mapping) { - storedProcedures.Add(mapping); + AddMapping(mapping, MappingType.StoredProcedure); } public bool Equals(MappedMembers other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return other.properties.ContentEquals(properties) && - other.collections.ContentEquals(collections) && - other.references.ContentEquals(references) && - other.components.ContentEquals(components) && - other.oneToOnes.ContentEquals(oneToOnes) && - other.anys.ContentEquals(anys) && - other.joins.ContentEquals(joins) && - other.filters.ContentEquals(filters) && - other.storedProcedures.ContentEquals(storedProcedures); + return other.orderedMappings.ContentEquals(orderedMappings); } public override bool Equals(object obj) @@ -251,22 +203,23 @@ public override bool Equals(object obj) return Equals((MappedMembers)obj); } - public override int GetHashCode() - { - unchecked - { - int result = (properties != null ? properties.GetHashCode() : 0); - result = (result * 397) ^ (collections != null ? collections.GetHashCode() : 0); - result = (result * 397) ^ (references != null ? references.GetHashCode() : 0); - result = (result * 397) ^ (components != null ? components.GetHashCode() : 0); - result = (result * 397) ^ (oneToOnes != null ? oneToOnes.GetHashCode() : 0); - result = (result * 397) ^ (anys != null ? anys.GetHashCode() : 0); - result = (result * 397) ^ (joins != null ? joins.GetHashCode() : 0); - result = (result * 397) ^ (filters != null ? filters.GetHashCode() : 0); - result = (result * 397) ^ (storedProcedures != null ? storedProcedures.GetHashCode() : 0); - return result; - } + public override int GetHashCode() { + return orderedMappings.GetHashCode(); + } + + private void AddMapping(TMapping mapping, MappingType mappingType) where TMapping : IMapping { + orderedMappings.Add(Tuple.Create(mappingType, (IMapping)mapping)); + } + + private void AddOrReplaceMapping(TMapping mapping, MappingType mappingType, Predicate matchPredicate) { + var newMapping = Tuple.Create(mappingType, (IMapping)mapping); + var index = orderedMappings.FindIndex(x => x.Item1 == mappingType && matchPredicate((TMapping)x.Item2)); + if (index >= 0) + orderedMappings[index] = newMapping; + else + orderedMappings.Add(newMapping); } } } + diff --git a/src/FluentNHibernate/Utils/ObservableDictionary.cs b/src/FluentNHibernate/Utils/ObservableDictionary.cs new file mode 100644 index 000000000..2931d2155 --- /dev/null +++ b/src/FluentNHibernate/Utils/ObservableDictionary.cs @@ -0,0 +1,225 @@ +using System; +using System.Collections; +using System.Linq; +using System.ComponentModel; +using System.Collections.Generic; +using System.Collections.Specialized; + +namespace FluentNHibernate.Utils { + + public class ObservableDictionary : IDictionary, INotifyCollectionChanged, INotifyPropertyChanged { + private const string CountString = "Count"; + private const string IndexerName = "Item[]"; + private const string KeysName = "Keys"; + private const string ValuesName = "Values"; + + private IDictionary _dictionary; + + protected IDictionary Dictionary { + get { return _dictionary; } + } + + #region Constructors + + public ObservableDictionary() { + _dictionary = new Dictionary(); + } + + public ObservableDictionary(IDictionary dictionary) { + _dictionary = new Dictionary(dictionary); + } + + public ObservableDictionary(IEqualityComparer comparer) { + _dictionary = new Dictionary(comparer); + } + + public ObservableDictionary(int capacity) { + _dictionary = new Dictionary(capacity); + } + + public ObservableDictionary(IDictionary dictionary, IEqualityComparer comparer) { + _dictionary = new Dictionary(dictionary, comparer); + } + + public ObservableDictionary(int capacity, IEqualityComparer comparer) { + _dictionary = new Dictionary(capacity, comparer); + } + + #endregion + + #region IDictionary Members + + public void Add(TKey key, TValue value) { + Insert(key, value, true); + } + + public bool ContainsKey(TKey key) { + return Dictionary.ContainsKey(key); + } + + public ICollection Keys { + get { return Dictionary.Keys; } + } + + public bool Remove(TKey key) { + if (key == null) throw new ArgumentNullException("key"); + + TValue value; + Dictionary.TryGetValue(key, out value); + var removed = Dictionary.Remove(key); + if (removed) + //OnCollectionChanged(NotifyCollectionChangedAction.Remove, new KeyValuePair(key, value)); + OnCollectionChanged(); + return removed; + } + + public bool TryGetValue(TKey key, out TValue value) { + return Dictionary.TryGetValue(key, out value); + } + + public ICollection Values { + get { return Dictionary.Values; } + } + + public TValue this[TKey key] { + get { + TValue value; + return TryGetValue(key, out value) ? value : default(TValue); + } + set { Insert(key, value, false); } + } + + #endregion + + #region ICollection> Members + + public void Add(KeyValuePair item) { + Insert(item.Key, item.Value, true); + } + + public void Clear() { + if (Dictionary.Count > 0) { + Dictionary.Clear(); + OnCollectionChanged(); + } + } + + public bool Contains(KeyValuePair item) { + return Dictionary.Contains(item); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) { + Dictionary.CopyTo(array, arrayIndex); + } + + public int Count { + get { return Dictionary.Count; } + } + + public bool IsReadOnly { + get { return Dictionary.IsReadOnly; } + } + + public bool Remove(KeyValuePair item) { + return Remove(item.Key); + } + + + #endregion + + #region IEnumerable> Members + + public IEnumerator> GetEnumerator() { + return Dictionary.GetEnumerator(); + } + + #endregion + + #region IEnumerable Members + + IEnumerator IEnumerable.GetEnumerator() { + return ((IEnumerable)Dictionary).GetEnumerator(); + } + + #endregion + + #region INotifyCollectionChanged Members + + public event NotifyCollectionChangedEventHandler CollectionChanged; + + #endregion + + #region INotifyPropertyChanged Members + + public event PropertyChangedEventHandler PropertyChanged; + + #endregion + + public void AddRange(IDictionary items) { + if (items == null) throw new ArgumentNullException("items"); + + if (items.Count > 0) { + if (Dictionary.Count > 0) { + if (items.Keys.Any((k) => Dictionary.ContainsKey(k))) + throw new ArgumentException("An item with the same key has already been added."); + else + foreach (var item in items) Dictionary.Add(item); + } else + _dictionary = new Dictionary(items); + + OnCollectionChanged(NotifyCollectionChangedAction.Add, items.ToArray()); + } + } + + private void Insert(TKey key, TValue value, bool add) { + if (key == null) throw new ArgumentNullException("key"); + + TValue item; + if (Dictionary.TryGetValue(key, out item)) { + if (add) throw new ArgumentException("An item with the same key has already been added."); + if (Equals(item, value)) return; + Dictionary[key] = value; + + OnCollectionChanged(NotifyCollectionChangedAction.Replace, new KeyValuePair(key, value), new KeyValuePair(key, item)); + OnPropertyChanged(key.ToString()); + } else { + Dictionary[key] = value; + + OnCollectionChanged(NotifyCollectionChangedAction.Add, new KeyValuePair(key, value)); + OnPropertyChanged(key.ToString()); + } + } + + private void OnPropertyChanged() { + OnPropertyChanged(CountString); + OnPropertyChanged(IndexerName); + OnPropertyChanged(KeysName); + OnPropertyChanged(ValuesName); + } + + protected virtual void OnPropertyChanged(string propertyName) { + if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + + private void OnCollectionChanged() { + OnPropertyChanged(); + if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair changedItem) { + OnPropertyChanged(); + if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, changedItem, 0)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair newItem, KeyValuePair oldItem) { + OnPropertyChanged(); + if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem, 0)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, IList newItems) { + OnPropertyChanged(); + if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItems, 0)); + } + + } +} From a62e46bface7f5fcce606bc6ff54341222de4dd1 Mon Sep 17 00:00:00 2001 From: Herman Schoenfeld Date: Thu, 27 Dec 2018 17:22:02 +1000 Subject: [PATCH 2/2] Cosmetic: code cleanup --- .../Mapping/MappingProviderStore.cs | 76 ++++++++----------- src/FluentNHibernate/Mapping/SubclassMap.cs | 14 ++-- .../Utils/ObservableDictionary.cs | 40 ++++------ 3 files changed, 52 insertions(+), 78 deletions(-) diff --git a/src/FluentNHibernate/Mapping/MappingProviderStore.cs b/src/FluentNHibernate/Mapping/MappingProviderStore.cs index 2e8d34518..010f58727 100644 --- a/src/FluentNHibernate/Mapping/MappingProviderStore.cs +++ b/src/FluentNHibernate/Mapping/MappingProviderStore.cs @@ -45,14 +45,12 @@ public enum ProviderType { private INaturalIdMappingProvider _naturalId; private IVersionMappingProvider _version; private IDiscriminatorMappingProvider _discriminator; - private TuplizerMapping _tuplizerMapping; - private IList> orderedProviders; + private TuplizerMapping _tupilizerMapping; + private readonly IList> _orderedProviders; public IIdentityMappingProvider Id { - get { - return _id; - } + get => _id; set { ReplaceOrAddProvider(ProviderType.Identity, _id, value); _id = value; @@ -60,9 +58,7 @@ public IIdentityMappingProvider Id { } public ICompositeIdMappingProvider CompositeId { - get { - return _compositeId; - } + get => _compositeId; set { ReplaceOrAddProvider(ProviderType.CompositeId, _compositeId, value); _compositeId = value; @@ -70,9 +66,7 @@ public ICompositeIdMappingProvider CompositeId { } public INaturalIdMappingProvider NaturalId { - get { - return _naturalId; - } + get => _naturalId; set { ReplaceOrAddProvider(ProviderType.NaturalId, _naturalId, value); _naturalId = value; @@ -80,9 +74,7 @@ public INaturalIdMappingProvider NaturalId { } public IVersionMappingProvider Version { - get { - return _version; - } + get => _version; set { ReplaceOrAddProvider(ProviderType.Version, _version, value); _version = value; @@ -90,9 +82,7 @@ public IVersionMappingProvider Version { } public IDiscriminatorMappingProvider Discriminator { - get { - return _discriminator; - } + get => _discriminator; set { ReplaceOrAddProvider(ProviderType.Discriminator, _discriminator, value); _discriminator = value; @@ -100,12 +90,10 @@ public IDiscriminatorMappingProvider Discriminator { } public TuplizerMapping TuplizerMapping { - get { - return _tuplizerMapping; - } + get => _tupilizerMapping; set { - ReplaceOrAddProvider(ProviderType.Tupilizer, _tuplizerMapping, value); - _tuplizerMapping = value; + ReplaceOrAddProvider(ProviderType.Tupilizer, _tupilizerMapping, value); + _tupilizerMapping = value; } } @@ -121,34 +109,34 @@ public MappingProviderStore() Filters = NewObservedList(); StoredProcedures = NewObservedList(); Joins = NewObservedList(); - orderedProviders = new List>(); + _orderedProviders = new List>(); } public IEnumerable> OrderedProviders { - get { return orderedProviders.Select(x => x); } + get { return _orderedProviders.Select(x => x); } } private IList NewObservedList() { - ProviderType TypeSelector(object o) + ProviderType TypeSelector(object mappingStoreCollection) { - if (ReferenceEquals(o, Properties)) { + if (ReferenceEquals(mappingStoreCollection, Properties)) { return ProviderType.Property; - } else if (ReferenceEquals(o, Components)) { + } else if (ReferenceEquals(mappingStoreCollection, Components)) { return ProviderType.Component; - } else if (ReferenceEquals(o, OneToOnes)) { + } else if (ReferenceEquals(mappingStoreCollection, OneToOnes)) { return ProviderType.OneToOne; - } else if (ReferenceEquals(o, Collections)) { + } else if (ReferenceEquals(mappingStoreCollection, Collections)) { return ProviderType.Collection; - } else if (ReferenceEquals(o, References)) { + } else if (ReferenceEquals(mappingStoreCollection, References)) { return ProviderType.ManyToOne; - } else if (ReferenceEquals(o, Anys)) { + } else if (ReferenceEquals(mappingStoreCollection, Anys)) { return ProviderType.Any; - } else if (ReferenceEquals(o, Filters)) { + } else if (ReferenceEquals(mappingStoreCollection, Filters)) { return ProviderType.Filter; - } else if (ReferenceEquals(o, StoredProcedures)) { + } else if (ReferenceEquals(mappingStoreCollection, StoredProcedures)) { return ProviderType.StoredProcedure; - } else if (ReferenceEquals(o, Joins)) { + } else if (ReferenceEquals(mappingStoreCollection, Joins)) { return ProviderType.Join; } throw new Exception("Internal Error"); @@ -160,20 +148,20 @@ ProviderType TypeSelector(object o) switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var newItem in args.NewItems) - orderedProviders.Add(Tuple.Create(type, newItem)); + _orderedProviders.Add(Tuple.Create(type, newItem)); break; case NotifyCollectionChangedAction.Move: throw new NotSupportedException(); case NotifyCollectionChangedAction.Remove: foreach (var oldItem in args.OldItems) - orderedProviders.Remove(Tuple.Create(type, oldItem)); + _orderedProviders.Remove(Tuple.Create(type, oldItem)); break; case NotifyCollectionChangedAction.Replace: throw new NotSupportedException(); case NotifyCollectionChangedAction.Reset: foreach (var oldItem in args.OldItems) - orderedProviders.Remove(Tuple.Create(type, oldItem)); + _orderedProviders.Remove(Tuple.Create(type, oldItem)); break; } }; @@ -189,12 +177,12 @@ private IDictionary NewObservedDictionary() { //Inserting for (var i = 0; i < args.NewItems.Count; i++) { var newValue = (KeyValuePair)args.NewItems[i]; - orderedProviders.Insert(args.NewStartingIndex + i, Tuple.Create(ProviderType.Subclass, (object)newValue.Value)); + _orderedProviders.Insert(args.NewStartingIndex + i, Tuple.Create(ProviderType.Subclass, (object)newValue.Value)); } } else { //Appending foreach (KeyValuePair newItem in args.NewItems) { - orderedProviders.Add(Tuple.Create(ProviderType.Subclass, (object)newItem.Value)); + _orderedProviders.Add(Tuple.Create(ProviderType.Subclass, (object)newItem.Value)); } } break; @@ -202,13 +190,13 @@ private IDictionary NewObservedDictionary() { throw new NotSupportedException(); case NotifyCollectionChangedAction.Remove: foreach (KeyValuePair oldItem in args.OldItems) - orderedProviders.Remove(Tuple.Create(ProviderType.Subclass, (object)oldItem.Value)); + _orderedProviders.Remove(Tuple.Create(ProviderType.Subclass, (object)oldItem.Value)); break; case NotifyCollectionChangedAction.Replace: throw new NotSupportedException(); case NotifyCollectionChangedAction.Reset: foreach (KeyValuePair oldItem in args.OldItems) - orderedProviders.Remove(Tuple.Create(ProviderType.Subclass, (object)oldItem.Value)); + _orderedProviders.Remove(Tuple.Create(ProviderType.Subclass, (object)oldItem.Value)); break; } }; @@ -216,12 +204,12 @@ private IDictionary NewObservedDictionary() { } private void ReplaceOrAddProvider(ProviderType type, object oldObj, object newObj) { - var index = orderedProviders.IndexOf(Tuple.Create(type, oldObj)); + var index = _orderedProviders.IndexOf(Tuple.Create(type, oldObj)); var newObjTuple = Tuple.Create(type, newObj); if (index > 0) - orderedProviders[index] = newObjTuple; + _orderedProviders[index] = newObjTuple; else - orderedProviders.Add(newObjTuple); + _orderedProviders.Add(newObjTuple); } } } \ No newline at end of file diff --git a/src/FluentNHibernate/Mapping/SubclassMap.cs b/src/FluentNHibernate/Mapping/SubclassMap.cs index ee9e00bf1..98ad6294e 100644 --- a/src/FluentNHibernate/Mapping/SubclassMap.cs +++ b/src/FluentNHibernate/Mapping/SubclassMap.cs @@ -310,25 +310,25 @@ SubclassMapping IIndeterminateSubclassMappingProvider.GetSubclassMapping(Subclas mapping.AddJoin(join); foreach (var provider in providers.OrderedProviders) { - var x = provider.Item2; + var mappingProviderObj = provider.Item2; switch (provider.Item1) { case MappingProviderStore.ProviderType.Property: - mapping.AddProperty(((IPropertyMappingProvider)x).GetPropertyMapping()); + mapping.AddProperty(((IPropertyMappingProvider)mappingProviderObj).GetPropertyMapping()); break; case MappingProviderStore.ProviderType.Component: - mapping.AddComponent(((IComponentMappingProvider)x).GetComponentMapping()); + mapping.AddComponent(((IComponentMappingProvider)mappingProviderObj).GetComponentMapping()); break; case MappingProviderStore.ProviderType.OneToOne: - mapping.AddOneToOne(((IOneToOneMappingProvider)x).GetOneToOneMapping()); + mapping.AddOneToOne(((IOneToOneMappingProvider)mappingProviderObj).GetOneToOneMapping()); break; case MappingProviderStore.ProviderType.Collection: - mapping.AddCollection(((ICollectionMappingProvider)x).GetCollectionMapping()); + mapping.AddCollection(((ICollectionMappingProvider)mappingProviderObj).GetCollectionMapping()); break; case MappingProviderStore.ProviderType.ManyToOne: - mapping.AddReference(((IManyToOneMappingProvider)x).GetManyToOneMapping()); + mapping.AddReference(((IManyToOneMappingProvider)mappingProviderObj).GetManyToOneMapping()); break; case MappingProviderStore.ProviderType.Any: - mapping.AddAny(((IAnyMappingProvider)x).GetAnyMapping()); + mapping.AddAny(((IAnyMappingProvider)mappingProviderObj).GetAnyMapping()); break; case MappingProviderStore.ProviderType.Subclass: case MappingProviderStore.ProviderType.Filter: diff --git a/src/FluentNHibernate/Utils/ObservableDictionary.cs b/src/FluentNHibernate/Utils/ObservableDictionary.cs index 2931d2155..5c81ee121 100644 --- a/src/FluentNHibernate/Utils/ObservableDictionary.cs +++ b/src/FluentNHibernate/Utils/ObservableDictionary.cs @@ -15,9 +15,7 @@ public class ObservableDictionary : IDictionary, INo private IDictionary _dictionary; - protected IDictionary Dictionary { - get { return _dictionary; } - } + protected IDictionary Dictionary => _dictionary; #region Constructors @@ -57,9 +55,7 @@ public bool ContainsKey(TKey key) { return Dictionary.ContainsKey(key); } - public ICollection Keys { - get { return Dictionary.Keys; } - } + public ICollection Keys => Dictionary.Keys; public bool Remove(TKey key) { if (key == null) throw new ArgumentNullException("key"); @@ -68,8 +64,7 @@ public bool Remove(TKey key) { Dictionary.TryGetValue(key, out value); var removed = Dictionary.Remove(key); if (removed) - //OnCollectionChanged(NotifyCollectionChangedAction.Remove, new KeyValuePair(key, value)); - OnCollectionChanged(); + OnCollectionChanged(NotifyCollectionChangedAction.Remove, new KeyValuePair(key, value)); return removed; } @@ -77,16 +72,11 @@ public bool TryGetValue(TKey key, out TValue value) { return Dictionary.TryGetValue(key, out value); } - public ICollection Values { - get { return Dictionary.Values; } - } + public ICollection Values => Dictionary.Values; public TValue this[TKey key] { - get { - TValue value; - return TryGetValue(key, out value) ? value : default(TValue); - } - set { Insert(key, value, false); } + get => TryGetValue(key, out var value) ? value : default(TValue); + set => Insert(key, value, false); } #endregion @@ -112,13 +102,9 @@ public void CopyTo(KeyValuePair[] array, int arrayIndex) { Dictionary.CopyTo(array, arrayIndex); } - public int Count { - get { return Dictionary.Count; } - } + public int Count => Dictionary.Count; - public bool IsReadOnly { - get { return Dictionary.IsReadOnly; } - } + public bool IsReadOnly => Dictionary.IsReadOnly; public bool Remove(KeyValuePair item) { return Remove(item.Key); @@ -198,27 +184,27 @@ private void OnPropertyChanged() { } protected virtual void OnPropertyChanged(string propertyName) { - if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void OnCollectionChanged() { OnPropertyChanged(); - if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair changedItem) { OnPropertyChanged(); - if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, changedItem, 0)); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, changedItem, 0)); } private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair newItem, KeyValuePair oldItem) { OnPropertyChanged(); - if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem, 0)); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem, 0)); } private void OnCollectionChanged(NotifyCollectionChangedAction action, IList newItems) { OnPropertyChanged(); - if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItems, 0)); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, newItems, 0)); } }