From 1203a17e71c9c7a19ff9d426b18ea375a985ef5b Mon Sep 17 00:00:00 2001 From: Herman Schoenfeld Date: Tue, 30 Apr 2024 22:24:29 +1000 Subject: [PATCH] ObjectSpaces: added annotations for building objects (and unit tests) --- src/Hydrogen/Comparers/ComparerFactory.cs | 28 +++++++--- .../Annotations/DimensionAttribute.cs | 7 +++ .../Annotations/IdentityAttribute.cs | 9 ++++ .../Annotations/IndexAttribute.cs | 6 +++ .../Annotations/IndexAttributeBase.cs | 10 ++++ .../Annotations/UniqueIndexAttribute.cs | 6 +++ .../Annotations/UseEqualityComparer.cs | 11 ++++ .../Builder/IObjectSpaceDimensionBuilder.cs | 11 ++++ .../Builder/ObjectSpaceBuilder.cs | 41 +++++++++++++-- .../Builder/ObjectSpaceDimensionBuilder.cs | 51 ++++++++++++++++--- .../ObjectSpaces/UniquePropertyAttribute.cs | 17 ------- .../ObjectSpaces/ObjectSpacesBuilderTest.cs | 47 ++++++++++++++--- .../ObjectSpaces/ObjectSpacesTestBase.cs | 11 ++-- tests/Hydrogen.Tests/TestObjects/Account.cs | 7 ++- .../TestObjects/AccountEqualityComparer.cs | 21 ++++++++ tests/Hydrogen.Tests/TestObjects/Identity.cs | 4 ++ 16 files changed, 239 insertions(+), 48 deletions(-) create mode 100644 src/Hydrogen/ObjectSpaces/Annotations/DimensionAttribute.cs create mode 100644 src/Hydrogen/ObjectSpaces/Annotations/IdentityAttribute.cs create mode 100644 src/Hydrogen/ObjectSpaces/Annotations/IndexAttribute.cs create mode 100644 src/Hydrogen/ObjectSpaces/Annotations/IndexAttributeBase.cs create mode 100644 src/Hydrogen/ObjectSpaces/Annotations/UniqueIndexAttribute.cs create mode 100644 src/Hydrogen/ObjectSpaces/Annotations/UseEqualityComparer.cs delete mode 100644 src/Hydrogen/ObjectSpaces/UniquePropertyAttribute.cs create mode 100644 tests/Hydrogen.Tests/TestObjects/AccountEqualityComparer.cs diff --git a/src/Hydrogen/Comparers/ComparerFactory.cs b/src/Hydrogen/Comparers/ComparerFactory.cs index 3c6a6688..5c06a1a5 100644 --- a/src/Hydrogen/Comparers/ComparerFactory.cs +++ b/src/Hydrogen/Comparers/ComparerFactory.cs @@ -123,8 +123,8 @@ public static void RegisterDefaults(ComparerFactory comparerFactory) { } - public IEqualityComparer GetEqualityComparer() - => (IEqualityComparer)GetEqualityComparer(typeof(T)); + public IEqualityComparer GetEqualityComparer() + => (IEqualityComparer)GetEqualityComparer(typeof(T)); public object GetEqualityComparer(Type type) { // Get registered comparer @@ -177,8 +177,8 @@ public object GetEqualityComparer(Type type) { return defaultComparer; } - public IComparer GetComparer() - => (IComparer)GetComparer(typeof(T)); + public IComparer GetComparer() + => (IComparer)GetComparer(typeof(T)); public object GetComparer(Type type) { // Get registered comparer @@ -198,12 +198,28 @@ public object GetComparer(Type type) { => RegisterComparer(new TComparer()); public void RegisterComparer(IComparer comparer) - => _comparers.Add(typeof(T), comparer); + => RegisterComparer(typeof(T), comparer); + + public void RegisterComparer(Type type, object comparer) { + Guard.ArgumentNotNull(type, nameof(type)); + Guard.ArgumentNotNull(comparer, nameof(comparer)); + Guard.Argument(comparer.GetType().IsSubtypeOfGenericType(typeof(IComparer<>), out var comparerInterfaceType), nameof(comparer), $"Not an {typeof(IComparer<>).ToStringCS()}"); + Guard.Argument(comparerInterfaceType.GenericTypeArguments[0] == type, nameof(comparer), $"Not an {typeof(IComparer<>).MakeGenericType(type).ToStringCS()}"); + _comparers.Add(type, comparer); + } public void RegisterEqualityComparer() where TEqualityComparer : IEqualityComparer, new() => RegisterEqualityComparer(new TEqualityComparer()); public void RegisterEqualityComparer(IEqualityComparer equalityComparer) - => _equalityComparers.Add(typeof(T), equalityComparer); + => RegisterEqualityComparer(typeof(T), equalityComparer); + + public void RegisterEqualityComparer(Type type, object equalityComparer) { + Guard.ArgumentNotNull(type, nameof(type)); + Guard.ArgumentNotNull(equalityComparer, nameof(equalityComparer)); + Guard.Argument(equalityComparer.GetType().IsSubtypeOfGenericType(typeof(IEqualityComparer<>), out var comparerInterfaceType), nameof(equalityComparer), $"Not an {typeof(IEqualityComparer<>).ToStringCS()}"); + Guard.Argument(comparerInterfaceType.GenericTypeArguments[0] == type, nameof(equalityComparer), $"Not an {typeof(IEqualityComparer<>).MakeGenericType(type).ToStringCS()}"); + _equalityComparers.Add(type, equalityComparer); + } } diff --git a/src/Hydrogen/ObjectSpaces/Annotations/DimensionAttribute.cs b/src/Hydrogen/ObjectSpaces/Annotations/DimensionAttribute.cs new file mode 100644 index 00000000..637e641d --- /dev/null +++ b/src/Hydrogen/ObjectSpaces/Annotations/DimensionAttribute.cs @@ -0,0 +1,7 @@ +using System; + +namespace Hydrogen; + +[AttributeUsage(AttributeTargets.Class)] +public class DimensionAttribute : Attribute { +} diff --git a/src/Hydrogen/ObjectSpaces/Annotations/IdentityAttribute.cs b/src/Hydrogen/ObjectSpaces/Annotations/IdentityAttribute.cs new file mode 100644 index 00000000..67d5a252 --- /dev/null +++ b/src/Hydrogen/ObjectSpaces/Annotations/IdentityAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace Hydrogen; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] +public class IdentityAttribute : Attribute { + public string IndexName { get; set; } = null; +} + diff --git a/src/Hydrogen/ObjectSpaces/Annotations/IndexAttribute.cs b/src/Hydrogen/ObjectSpaces/Annotations/IndexAttribute.cs new file mode 100644 index 00000000..b4d07f7d --- /dev/null +++ b/src/Hydrogen/ObjectSpaces/Annotations/IndexAttribute.cs @@ -0,0 +1,6 @@ +using System; + +namespace Hydrogen; + +public class IndexAttribute : IndexAttributeBase { +} diff --git a/src/Hydrogen/ObjectSpaces/Annotations/IndexAttributeBase.cs b/src/Hydrogen/ObjectSpaces/Annotations/IndexAttributeBase.cs new file mode 100644 index 00000000..baf7f7bb --- /dev/null +++ b/src/Hydrogen/ObjectSpaces/Annotations/IndexAttributeBase.cs @@ -0,0 +1,10 @@ +using System; + +namespace Hydrogen; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] +public abstract class IndexAttributeBase : Attribute { + public string IndexName { get; set; } = null; + + public IndexNullPolicy NullPolicy { get; set; } = IndexNullPolicy.IgnoreNull; +} diff --git a/src/Hydrogen/ObjectSpaces/Annotations/UniqueIndexAttribute.cs b/src/Hydrogen/ObjectSpaces/Annotations/UniqueIndexAttribute.cs new file mode 100644 index 00000000..fc318cb3 --- /dev/null +++ b/src/Hydrogen/ObjectSpaces/Annotations/UniqueIndexAttribute.cs @@ -0,0 +1,6 @@ +using System; + +namespace Hydrogen; + +public class UniqueIndexAttribute: IndexAttributeBase { +} diff --git a/src/Hydrogen/ObjectSpaces/Annotations/UseEqualityComparer.cs b/src/Hydrogen/ObjectSpaces/Annotations/UseEqualityComparer.cs new file mode 100644 index 00000000..af543de6 --- /dev/null +++ b/src/Hydrogen/ObjectSpaces/Annotations/UseEqualityComparer.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace Hydrogen; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] +public class EqualityComparerAttribute(Type type) : Attribute { + + public Type EqualityComparerType { get; } = type; + +} diff --git a/src/Hydrogen/ObjectSpaces/Builder/IObjectSpaceDimensionBuilder.cs b/src/Hydrogen/ObjectSpaces/Builder/IObjectSpaceDimensionBuilder.cs index 1b18e185..90885a60 100644 --- a/src/Hydrogen/ObjectSpaces/Builder/IObjectSpaceDimensionBuilder.cs +++ b/src/Hydrogen/ObjectSpaces/Builder/IObjectSpaceDimensionBuilder.cs @@ -6,6 +6,7 @@ // // This notice must not be removed when duplicating this file or its contents, in whole or in part. +using Hydrogen.Mapping; using System; using System.Collections.Generic; @@ -21,6 +22,16 @@ public interface IObjectSpaceDimensionBuilder { IObjectSpaceDimensionBuilder Merkleized(); + IObjectSpaceDimensionBuilder UsingComparer(object comparer); + + IObjectSpaceDimensionBuilder UsingEqualityComparer(object comparer); + + IObjectSpaceDimensionBuilder WithIdentifier(Member member, string indexName = null); + + IObjectSpaceDimensionBuilder WithIndexOn(Member member, string indexName = null, IndexNullPolicy nullPolicy = IndexNullPolicy.IgnoreNull); + + IObjectSpaceDimensionBuilder WithUniqueIndexOn(Member member, string indexName = null, IndexNullPolicy nullPolicy = IndexNullPolicy.IgnoreNull); + IObjectSpaceDimensionBuilder OptimizeAssumingAverageItemSize(int bytes); ObjectSpaceDefinition.DimensionDefinition BuildDefinition(); diff --git a/src/Hydrogen/ObjectSpaces/Builder/ObjectSpaceBuilder.cs b/src/Hydrogen/ObjectSpaces/Builder/ObjectSpaceBuilder.cs index c3f17539..a47c57c8 100644 --- a/src/Hydrogen/ObjectSpaces/Builder/ObjectSpaceBuilder.cs +++ b/src/Hydrogen/ObjectSpaces/Builder/ObjectSpaceBuilder.cs @@ -176,6 +176,13 @@ public ObjectSpaceBuilder UsingEqualityComparer(IEqualityComparer return this; } + public ObjectSpaceBuilder UsingEqualityComparer(Type type, object comparer) { + Guard.Against(_usingCustomComparerFactory, ErrMsgUsingComparer); + _specifiedCustomComparer = true; + _comparerFactory.RegisterEqualityComparer(type, comparer); + return this; + } + public ObjectSpaceBuilder UsingComparer() where TComparer : IComparer, new() { Guard.Against(_usingCustomComparerFactory, ErrMsgUsingComparer); _specifiedCustomComparer = true; @@ -190,10 +197,38 @@ public ObjectSpaceBuilder UsingComparer(IComparer comparer) { return this; } - public ObjectSpaceDimensionBuilder AddDimension() { - var dimensionBuilder = new ObjectSpaceDimensionBuilder(this); + public ObjectSpaceBuilder UsingComparer(Type type, object comparer) { + Guard.Against(_usingCustomComparerFactory, ErrMsgUsingComparer); + _specifiedCustomComparer = true; + _comparerFactory.RegisterComparer(type, comparer); + return this; + } + + public ObjectSpaceDimensionBuilder AddDimension(bool ignoreAnnotations = false) + => (ObjectSpaceDimensionBuilder)AddDimension(typeof(T), ignoreAnnotations); + + public IObjectSpaceDimensionBuilder AddDimension(Type type, bool ignoreAnnotations = false) { + var dimensionBuilder = (IObjectSpaceDimensionBuilder)typeof(ObjectSpaceDimensionBuilder<>).MakeGenericType(type).ActivateWithCompatibleArgs(this); _dimensions.Add(dimensionBuilder); - return Configure(); + + if (!ignoreAnnotations) { + + if (type.TryGetCustomAttributeOfType(false, out var equalityComparerAttribute)) + dimensionBuilder.UsingEqualityComparer(equalityComparerAttribute.EqualityComparerType.ActivateWithCompatibleArgs()); + + foreach(var member in SerializationHelper.GetSerializableMembers(type)) { + if (member.MemberInfo.TryGetCustomAttributeOfType(false, out var identityAttribute)) + dimensionBuilder.WithIdentifier(member, identityAttribute.IndexName); + + if (member.MemberInfo.TryGetCustomAttributeOfType(false, out var indexAttribute)) + dimensionBuilder.WithIndexOn(member, indexAttribute.IndexName, indexAttribute.NullPolicy); + + if (member.MemberInfo.TryGetCustomAttributeOfType(false, out var uniqueIndexAttribute)) + dimensionBuilder.WithUniqueIndexOn(member, uniqueIndexAttribute.IndexName, uniqueIndexAttribute.NullPolicy); + + } + } + return dimensionBuilder; } public ObjectSpaceDimensionBuilder Configure() { diff --git a/src/Hydrogen/ObjectSpaces/Builder/ObjectSpaceDimensionBuilder.cs b/src/Hydrogen/ObjectSpaces/Builder/ObjectSpaceDimensionBuilder.cs index a1ce503e..2c821de5 100644 --- a/src/Hydrogen/ObjectSpaces/Builder/ObjectSpaceDimensionBuilder.cs +++ b/src/Hydrogen/ObjectSpaces/Builder/ObjectSpaceDimensionBuilder.cs @@ -51,7 +51,15 @@ public ObjectSpaceDimensionBuilder UsingComparer(IComparer comparer) { _parent.UsingComparer(comparer); return this; } - + + public ObjectSpaceDimensionBuilder UsingComparer(object comparer) + => (ObjectSpaceDimensionBuilder)((IObjectSpaceDimensionBuilder)this).UsingComparer(comparer); + + IObjectSpaceDimensionBuilder IObjectSpaceDimensionBuilder.UsingComparer(object comparer) { + _parent.UsingComparer(typeof(T), comparer); + return this; + } + public ObjectSpaceDimensionBuilder UsingEqualityComparer() where TComparer : IEqualityComparer, new() { _parent.UsingEqualityComparer(); return this; @@ -62,8 +70,23 @@ public ObjectSpaceDimensionBuilder UsingEqualityComparer(IEqualityComparer return this; } - public ObjectSpaceDimensionBuilder WithIdentifier(Expression> memberExpression, string indexName = null) { - var member = memberExpression.ToMember(); + public ObjectSpaceDimensionBuilder UsingEqualityComparer(object comparer) + => (ObjectSpaceDimensionBuilder)((IObjectSpaceDimensionBuilder)this).UsingEqualityComparer(comparer); + + IObjectSpaceDimensionBuilder IObjectSpaceDimensionBuilder.UsingEqualityComparer(object comparer) { + _parent.UsingEqualityComparer(typeof(T), comparer); + return this; + } + + public ObjectSpaceDimensionBuilder WithIdentifier(Expression> memberExpression, string indexName = null) + => WithIdentifier(memberExpression.ToMember(), indexName); + + public new ObjectSpaceDimensionBuilder WithIdentifier(Member member, string indexName = null) + => (ObjectSpaceDimensionBuilder)((IObjectSpaceDimensionBuilder)this).WithIdentifier(member, indexName); + + IObjectSpaceDimensionBuilder IObjectSpaceDimensionBuilder.WithIdentifier(Member member, string indexName) { + Guard.ArgumentNotNull(member, nameof(member)); + Guard.Argument(member.DeclaringType == typeof(T), nameof(member), $"Not a member of {typeof(T).ToStringCS()}"); var index = new ObjectSpaceDefinition.IndexDefinition { Type = ObjectSpaceDefinition.IndexType.Identifier, Name = indexName ?? member.Name, @@ -73,9 +96,16 @@ public ObjectSpaceDimensionBuilder WithIdentifier(Expression WithIndexOn(Expression> memberExpression, string indexName = null, IndexNullPolicy nullPolicy = IndexNullPolicy.IgnoreNull) + => WithIndexOn(memberExpression.ToMember(), indexName, nullPolicy); + + public ObjectSpaceDimensionBuilder WithIndexOn(Member member, string indexName = null, IndexNullPolicy nullPolicy = IndexNullPolicy.IgnoreNull) + => (ObjectSpaceDimensionBuilder)((IObjectSpaceDimensionBuilder)this).WithIndexOn(member, indexName, nullPolicy); - public ObjectSpaceDimensionBuilder WithIndexOn(Expression> memberExpression, string indexName = null, IndexNullPolicy nullPolicy = IndexNullPolicy.IgnoreNull) { - var member = memberExpression.ToMember(); + IObjectSpaceDimensionBuilder IObjectSpaceDimensionBuilder.WithIndexOn(Member member, string indexName = null, IndexNullPolicy nullPolicy = IndexNullPolicy.IgnoreNull) { + Guard.ArgumentNotNull(member, nameof(member)); + Guard.Argument(member.DeclaringType == typeof(T), nameof(member), $"Not a member of {typeof(T).ToStringCS()}"); var index = new ObjectSpaceDefinition.IndexDefinition { Type = ObjectSpaceDefinition.IndexType.Index, Name = indexName ?? member.Name, @@ -86,8 +116,15 @@ public ObjectSpaceDimensionBuilder WithIndexOn(Expression WithUniqueIndexOn(Expression> memberExpression, string indexName = null, IndexNullPolicy nullPolicy = IndexNullPolicy.IgnoreNull) { - var member = memberExpression.ToMember(); + public ObjectSpaceDimensionBuilder WithUniqueIndexOn(Expression> memberExpression, string indexName = null, IndexNullPolicy nullPolicy = IndexNullPolicy.IgnoreNull) + => WithUniqueIndexOn(memberExpression.ToMember(), indexName, nullPolicy); + + public ObjectSpaceDimensionBuilder WithUniqueIndexOn(Member member, string indexName = null, IndexNullPolicy nullPolicy = IndexNullPolicy.IgnoreNull) + => (ObjectSpaceDimensionBuilder)((IObjectSpaceDimensionBuilder)this).WithUniqueIndexOn(member, indexName, nullPolicy); + + IObjectSpaceDimensionBuilder IObjectSpaceDimensionBuilder.WithUniqueIndexOn(Member member, string indexName = null, IndexNullPolicy nullPolicy = IndexNullPolicy.IgnoreNull) { + Guard.ArgumentNotNull(member, nameof(member)); + Guard.Argument(member.DeclaringType == typeof(T), nameof(member), $"Not a member of {typeof(T).ToStringCS()}"); var index = new ObjectSpaceDefinition.IndexDefinition { Type = ObjectSpaceDefinition.IndexType.UniqueKey, Name = indexName ?? member.Name, diff --git a/src/Hydrogen/ObjectSpaces/UniquePropertyAttribute.cs b/src/Hydrogen/ObjectSpaces/UniquePropertyAttribute.cs deleted file mode 100644 index 3f5d332d..00000000 --- a/src/Hydrogen/ObjectSpaces/UniquePropertyAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Sphere 10 Software. All rights reserved. (https://sphere10.com) -// Author: Herman Schoenfeld -// -// Distributed under the MIT software license, see the accompanying file -// LICENSE or visit http://www.opensource.org/licenses/mit-license.php. -// -// This notice must not be removed when duplicating this file or its contents, in whole or in part. - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Hydrogen.ObjectSpaces; - -public class UniquePropertyAttribute : Attribute { -} - diff --git a/tests/Hydrogen.Tests/ObjectSpaces/ObjectSpacesBuilderTest.cs b/tests/Hydrogen.Tests/ObjectSpaces/ObjectSpacesBuilderTest.cs index 273022b2..f34e994f 100644 --- a/tests/Hydrogen.Tests/ObjectSpaces/ObjectSpacesBuilderTest.cs +++ b/tests/Hydrogen.Tests/ObjectSpaces/ObjectSpacesBuilderTest.cs @@ -26,7 +26,7 @@ public void CannotRegisterSerializerWhenUsingCustomSerializerFactory_1() { var objectSpaceBuilder = new ObjectSpaceBuilder(); objectSpaceBuilder .UsingSerializerFactory(customSerializerFactory) - .AddDimension(); + .AddDimension(true); var serializer = SerializerBuilder.For().Build(); Assert.That(() => objectSpaceBuilder.Configure().UsingSerializer(serializer), Throws.InvalidOperationException); @@ -39,7 +39,7 @@ public void CannotRegisterSerializerWhenUsingCustomSerializerFactory_2() { var objectSpaceBuilder = new ObjectSpaceBuilder(); objectSpaceBuilder .UsingSerializerFactory(customSerializerFactory) - .AddDimension(); + .AddDimension(true); Assert.That(() => objectSpaceBuilder.Configure().UsingSerializer(), Throws.InvalidOperationException); } @@ -64,7 +64,7 @@ public void CannotRegisterComparerWhenUsingCustomComparerFactory_1() { var objectSpaceBuilder = new ObjectSpaceBuilder(); objectSpaceBuilder .UsingComparerFactory(customComparerFactory) - .AddDimension(); + .AddDimension(true); var comparer = ComparerBuilder.For(); Assert.That(() => objectSpaceBuilder.Configure().UsingComparer(comparer), Throws.InvalidOperationException); @@ -77,7 +77,7 @@ public void CannotRegisterComparerWhenUsingCustomComparerFactory_2() { var objectSpaceBuilder = new ObjectSpaceBuilder(); objectSpaceBuilder .UsingComparerFactory(customComparerFactory) - .AddDimension(); + .AddDimension(true); Assert.That(() => objectSpaceBuilder.Configure().UsingComparer(), Throws.InvalidOperationException); } @@ -89,7 +89,7 @@ public void CannotRegisterEqualityComparerWhenUsingCustomComparerFactory_1() { var objectSpaceBuilder = new ObjectSpaceBuilder(); objectSpaceBuilder .UsingComparerFactory(customComparerFactory) - .AddDimension(); + .AddDimension(true); var comparer = EqualityComparerBuilder.For(); Assert.That(() => objectSpaceBuilder.Configure().UsingEqualityComparer(comparer), Throws.InvalidOperationException); @@ -102,11 +102,46 @@ public void CannotRegisterEqualityComparerWhenUsingCustomComparerFactory_2() { var objectSpaceBuilder = new ObjectSpaceBuilder(); objectSpaceBuilder .UsingComparerFactory(customComparerFactory) - .AddDimension(); + .AddDimension(true); Assert.That(() => objectSpaceBuilder.Configure().UsingEqualityComparer(), Throws.InvalidOperationException); } + [Test] + public void Annotations() { + var customComparerFactory = new ComparerFactory(ComparerFactory.Default); + + var objectSpaceBuilder = new ObjectSpaceBuilder(); + objectSpaceBuilder + .UseMemoryStream() + .AddDimension().Done() + .AddDimension().Done(); + + + var definition = objectSpaceBuilder.BuildDefinition(); + + Assert.That(definition.Dimensions[0].Indexes.Count, Is.EqualTo(3)); + + // Account + Assert.That(definition.Dimensions[0].Indexes[1].Type, Is.EqualTo(ObjectSpaceDefinition.IndexType.Identifier)); + Assert.That(definition.Dimensions[0].Indexes[1].Member, Is.EqualTo(Tools.Mapping.GetMember(x => x.Name))); + + Assert.That(definition.Dimensions[0].Indexes[2].Type, Is.EqualTo(ObjectSpaceDefinition.IndexType.UniqueKey)); + Assert.That(definition.Dimensions[0].Indexes[2].Member, Is.EqualTo(Tools.Mapping.GetMember(x => x.UniqueNumber))); + + // Identity + Assert.That(definition.Dimensions[1].Indexes[1].Type, Is.EqualTo(ObjectSpaceDefinition.IndexType.UniqueKey)); + Assert.That(definition.Dimensions[1].Indexes[1].Member, Is.EqualTo(Tools.Mapping.GetMember(x => x.Key))); + + Assert.That(definition.Dimensions[1].Indexes[2].Type, Is.EqualTo(ObjectSpaceDefinition.IndexType.Index)); + Assert.That(definition.Dimensions[1].Indexes[2].Member, Is.EqualTo(Tools.Mapping.GetMember(x => x.Group))); + + // Test comparer + var objectSpace = objectSpaceBuilder.Build(); + Assert.That( () => objectSpace.Comparers.GetEqualityComparer(), Is.InstanceOf()); + + } + internal class DummyAccountSerializer : ItemSerializerBase { public override long CalculateSize(SerializationContext context, Account item) { diff --git a/tests/Hydrogen.Tests/ObjectSpaces/ObjectSpacesTestBase.cs b/tests/Hydrogen.Tests/ObjectSpaces/ObjectSpacesTestBase.cs index cd8046e5..5ce0cfae 100644 --- a/tests/Hydrogen.Tests/ObjectSpaces/ObjectSpacesTestBase.cs +++ b/tests/Hydrogen.Tests/ObjectSpaces/ObjectSpacesTestBase.cs @@ -25,12 +25,12 @@ protected ObjectSpaceBuilder CreateStandardObjectSpace() { var builder = new ObjectSpaceBuilder(); builder .AutoLoad() - .AddDimension() + .AddDimension(true) .WithUniqueIndexOn(x => x.Name) .WithUniqueIndexOn(x => x.UniqueNumber) .UsingEqualityComparer(CreateAccountComparer()) .Done() - .AddDimension() + .AddDimension(true) .WithUniqueIndexOn(x => x.Key) .UsingEqualityComparer(CreateIdentityComparer()) .Done(); @@ -42,12 +42,12 @@ protected ObjectSpaceBuilder CreateNullTestingbjectSpace(IndexNullPolicy nullVal var builder = new ObjectSpaceBuilder(); builder .AutoLoad() - .AddDimension() + .AddDimension(true) .WithUniqueIndexOn(x => x.Name, nullPolicy: nullValuePolicy) .WithUniqueIndexOn(x => x.UniqueNumber, nullPolicy: nullValuePolicy) .UsingEqualityComparer(CreateAccountComparer()) .Done() - .AddDimension() + .AddDimension(true) .WithUniqueIndexOn(x => x.Key) .UsingEqualityComparer(CreateIdentityComparer()) .Done(); @@ -91,8 +91,6 @@ public void DeleteThrowsNothing() { #endregion - - #region Clear [Test] @@ -268,7 +266,6 @@ public void UniqueMember_GetViaIndex() { Assert.That(() => objectSpace.Get((Account x) => x.UniqueNumber, 3), Throws.InvalidOperationException); } - [Test] public void UniqueMember_ProhibitsDuplicate_ViaAdd() { // note: long based property will index the property value (not checksum) since constant length key diff --git a/tests/Hydrogen.Tests/TestObjects/Account.cs b/tests/Hydrogen.Tests/TestObjects/Account.cs index 6cf91bac..c2759311 100644 --- a/tests/Hydrogen.Tests/TestObjects/Account.cs +++ b/tests/Hydrogen.Tests/TestObjects/Account.cs @@ -1,16 +1,19 @@ -using System; +using System.Collections; using Hydrogen.ObjectSpaces; namespace Hydrogen.Tests; +[EqualityComparer(typeof(AccountEqualityComparer))] public class Account { + [Identity] public string Name { get; set; } public decimal Quantity { get; set; } + [UniqueIndex] public long UniqueNumber { get; set; } public Identity Identity { get; set; } -} +} \ No newline at end of file diff --git a/tests/Hydrogen.Tests/TestObjects/AccountEqualityComparer.cs b/tests/Hydrogen.Tests/TestObjects/AccountEqualityComparer.cs new file mode 100644 index 00000000..56a2d64b --- /dev/null +++ b/tests/Hydrogen.Tests/TestObjects/AccountEqualityComparer.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace Hydrogen.Tests; + +public class AccountEqualityComparer : IEqualityComparer { + public bool Equals(Account x, Account y) { + if (ReferenceEquals(x, y)) + return true; + if (ReferenceEquals(x, null)) + return false; + if (ReferenceEquals(y, null)) + return false; + if (x.GetType() != y.GetType()) + return false; + return x.Name == y.Name && x.Quantity == y.Quantity && x.UniqueNumber == y.UniqueNumber && Equals(x.Identity, y.Identity); + } + public int GetHashCode(Account obj) { + return HashCode.Combine(obj.Name, obj.Quantity, obj.UniqueNumber, obj.Identity); + } +} diff --git a/tests/Hydrogen.Tests/TestObjects/Identity.cs b/tests/Hydrogen.Tests/TestObjects/Identity.cs index e4247fe2..9b98a7b0 100644 --- a/tests/Hydrogen.Tests/TestObjects/Identity.cs +++ b/tests/Hydrogen.Tests/TestObjects/Identity.cs @@ -6,5 +6,9 @@ public class Identity { public DSS DSS { get; set; } + [UniqueIndex] public byte[] Key { get; set; } + + [Index] + public int Group { get; set; } }