diff --git a/Detached.Mappers.sln b/Detached.Mappers.sln index 5b40de9c..4e8b8755 100644 --- a/Detached.Mappers.sln +++ b/Detached.Mappers.sln @@ -42,8 +42,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Detached.Mappers.HotChocola EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "contrib", "contrib", "{5409CE02-02AD-448B-85A5-EFEABA6C52C8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Detached.Mappers.Annotation.Tests", "test\Detached.Mappers.Annotation.Tests\Detached.Mappers.Annotation.Tests.csproj", "{713EB397-9271-45F6-811C-CD84CD6BB194}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -94,10 +92,6 @@ Global {B6162ECF-00B0-4506-B3E8-2A4B46517ECE}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6162ECF-00B0-4506-B3E8-2A4B46517ECE}.Release|Any CPU.ActiveCfg = Release|Any CPU {B6162ECF-00B0-4506-B3E8-2A4B46517ECE}.Release|Any CPU.Build.0 = Release|Any CPU - {713EB397-9271-45F6-811C-CD84CD6BB194}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {713EB397-9271-45F6-811C-CD84CD6BB194}.Debug|Any CPU.Build.0 = Debug|Any CPU - {713EB397-9271-45F6-811C-CD84CD6BB194}.Release|Any CPU.ActiveCfg = Release|Any CPU - {713EB397-9271-45F6-811C-CD84CD6BB194}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -116,7 +110,6 @@ Global {42962E94-05D1-4D67-8BB2-572B04CBC3F7} = {C9521C36-FBA4-4B3E-AE14-A1735E9D1E71} {B6162ECF-00B0-4506-B3E8-2A4B46517ECE} = {42962E94-05D1-4D67-8BB2-572B04CBC3F7} {5409CE02-02AD-448B-85A5-EFEABA6C52C8} = {745CB1E1-F50B-4307-8BD6-1ADDC837102B} - {713EB397-9271-45F6-811C-CD84CD6BB194} = {C9521C36-FBA4-4B3E-AE14-A1735E9D1E71} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7FC47439-B36B-45BB-BEEC-A6D595358C63} diff --git a/src/Detached.Mappers.EntityFramework/Options/EntityMapperOptions.cs b/src/Detached.Mappers.EntityFramework/Configuration/EntityMapperOptions.cs similarity index 100% rename from src/Detached.Mappers.EntityFramework/Options/EntityMapperOptions.cs rename to src/Detached.Mappers.EntityFramework/Configuration/EntityMapperOptions.cs diff --git a/src/Detached.Mappers.EntityFramework/Options/EntityMapperOptionsBuilder.cs b/src/Detached.Mappers.EntityFramework/Configuration/EntityMapperOptionsBuilder.cs similarity index 100% rename from src/Detached.Mappers.EntityFramework/Options/EntityMapperOptionsBuilder.cs rename to src/Detached.Mappers.EntityFramework/Configuration/EntityMapperOptionsBuilder.cs diff --git a/src/Detached.Mappers.EntityFramework/Configuration/IEntityMapperConfiguration.cs b/src/Detached.Mappers.EntityFramework/Configuration/IEntityMapperConfiguration.cs new file mode 100644 index 00000000..c83691fb --- /dev/null +++ b/src/Detached.Mappers.EntityFramework/Configuration/IEntityMapperConfiguration.cs @@ -0,0 +1,7 @@ +namespace Detached.Mappers.EntityFramework.Configuration +{ + public interface IEntityMapperConfiguration + { + void Apply(EntityMapperOptionsBuilder builder); + } +} diff --git a/src/Detached.Mappers.EntityFramework/Conventions/EntityTypeConventions.cs b/src/Detached.Mappers.EntityFramework/Conventions/EntityTypeConventions.cs index 0a6b5619..6c005be6 100644 --- a/src/Detached.Mappers.EntityFramework/Conventions/EntityTypeConventions.cs +++ b/src/Detached.Mappers.EntityFramework/Conventions/EntityTypeConventions.cs @@ -1,6 +1,8 @@ using Detached.Mappers.Types; using Detached.Mappers.Types.Class; using Microsoft.EntityFrameworkCore.Metadata; +using System; +using System.Collections.Generic; using System.Linq; namespace Detached.Mappers.EntityFramework.Conventions @@ -63,15 +65,16 @@ void SetDiscriminator(ClassType classType, IEntityType entityType) IProperty discriminator = entityType.FindDiscriminatorProperty(); if (discriminator != null && (entityType.BaseType == null || entityType.IsAbstract())) { - classType.SetDiscriminatorName(discriminator.Name); - + var values = new Dictionary(); foreach (var inheritedType in entityType.Model.GetEntityTypes()) { if (IsBaseType(inheritedType, entityType)) { - classType.GetDiscriminatorValues()[inheritedType.GetDiscriminatorValue()] = inheritedType.ClrType; + values[inheritedType.GetDiscriminatorValue()] = inheritedType.ClrType; } } + + classType.SetDiscriminator(discriminator.Name, values); } } diff --git a/src/Detached.Mappers.EntityFramework/Options/IEntityMapperCustomizer.cs b/src/Detached.Mappers.EntityFramework/Options/IEntityMapperCustomizer.cs deleted file mode 100644 index 87bc0c75..00000000 --- a/src/Detached.Mappers.EntityFramework/Options/IEntityMapperCustomizer.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Detached.Mappers.EntityFramework.Configuration -{ - public interface IEntityMapperCustomizer - { - void Customize(EntityMapperOptionsBuilder builder); - } -} diff --git a/src/Detached.Mappers.EntityFramework/Package.cs b/src/Detached.Mappers.EntityFramework/Package.cs index c2830d57..eddd63a8 100644 --- a/src/Detached.Mappers.EntityFramework/Package.cs +++ b/src/Detached.Mappers.EntityFramework/Package.cs @@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using System; +using System.Collections.Generic; namespace Detached.Mappers.EntityFramework { @@ -14,28 +15,32 @@ public static DbContextOptionsBuilder UseMapping(this DbContextOptionsBuilder db configure?.Invoke(builder); - AddMappingExtension(dbContextBuilder, builder.Options); + UseMapping(dbContextBuilder, builder.Options); return dbContextBuilder; } - public static DbContextOptionsBuilder UseMapping(this DbContextOptionsBuilder dbContextBuilder, Action configure = null) - where TDbContext : DbContext + public static DbContextOptionsBuilder UseMapping(this DbContextOptionsBuilder dbContextBuilder, IEnumerable configs) { var builder = new EntityMapperOptionsBuilder(); - configure?.Invoke(builder); + foreach (var config in configs) + { + config.Apply(builder); + } - AddMappingExtension(dbContextBuilder, builder.Options); + UseMapping(dbContextBuilder, builder.Options); return dbContextBuilder; } - static void AddMappingExtension(DbContextOptionsBuilder dbContextBuilder, EntityMapperOptions options) + public static DbContextOptionsBuilder UseMapping(this DbContextOptionsBuilder dbContextBuilder, EntityMapperOptions options) { var builder = ((IDbContextOptionsBuilderInfrastructure)dbContextBuilder); builder.AddOrUpdateExtension(new EntityMapperDbContextOptionsExtension(dbContextBuilder.Options.ContextType, options)); + + return dbContextBuilder; } } } \ No newline at end of file diff --git a/src/Detached.Mappers/Annotations/Extensions/AbstractAnnotationExtensions.cs b/src/Detached.Mappers/Annotations/Extensions/AbstractAnnotationExtensions.cs index daa8abdb..4a8fef97 100644 --- a/src/Detached.Mappers/Annotations/Extensions/AbstractAnnotationExtensions.cs +++ b/src/Detached.Mappers/Annotations/Extensions/AbstractAnnotationExtensions.cs @@ -24,5 +24,10 @@ public static ClassTypeBuilder Abstract(this ClassTypeBuilder values) { - return type.Annotations.DiscriminatorName().Value(); - } + var propertyNameAnnotation = type.Annotations.DiscriminatorName(); + var valuesAnnotation = type.Annotations.DiscriminatorValues(); - public static IType SetDiscriminatorName(this IType type, string name) - { - type.Annotations.DiscriminatorName().Set(name); + propertyNameAnnotation.Set(propertyName); + valuesAnnotation.Set(values); return type; } - public static Dictionary GetDiscriminatorValues(this IType type) + public static bool GetDiscriminator(this IType type, out string propertyName, out Dictionary values) { - var annotation = type.Annotations.DiscriminatorValues(); + var propertyNameAnnotation = type.Annotations.DiscriminatorName(); + var valuesAnnotation = type.Annotations.DiscriminatorValues(); - if (!annotation.IsDefined()) - { - annotation.Set(new()); - } + propertyName = propertyNameAnnotation.Value(); + values = valuesAnnotation.Value(); - return annotation.Value(); + return propertyNameAnnotation.IsDefined() && valuesAnnotation.IsDefined(); } } } diff --git a/src/Detached.Mappers/MapperOptions.cs b/src/Detached.Mappers/MapperOptions.cs index 66fbb35a..5062fec0 100644 --- a/src/Detached.Mappers/MapperOptions.cs +++ b/src/Detached.Mappers/MapperOptions.cs @@ -227,8 +227,8 @@ public virtual bool IsPrimitive(Type type) public virtual bool ShouldMap(IType sourceType, IType targetType) { return sourceType != targetType - || sourceType.Annotations.Abstract().Value() - || targetType.Annotations.Abstract().Value() + || sourceType.IsAbstract() + || targetType.IsAbstract() || (targetType.IsComplex() || targetType.IsCollection() && GetType(targetType.ItemClrType).IsComplex()); } diff --git a/src/Detached.Mappers/TypeBinders/Binders/InheritedTypeBinder.cs b/src/Detached.Mappers/TypeBinders/Binders/InheritedTypeBinder.cs index 75653384..a41bd7a1 100644 --- a/src/Detached.Mappers/TypeBinders/Binders/InheritedTypeBinder.cs +++ b/src/Detached.Mappers/TypeBinders/Binders/InheritedTypeBinder.cs @@ -13,20 +13,20 @@ public bool CanBind(Mapper mapper, TypePair typePair) { return typePair.SourceType.IsComplex() && typePair.TargetType.IsComplex() - && typePair.SourceType.GetDiscriminatorName() != null - && typePair.TargetType.GetDiscriminatorName() != null; + && typePair.SourceType.GetDiscriminator(out _, out _) + && typePair.TargetType.GetDiscriminator(out _, out _); } public Expression Bind(Mapper mapper, TypePair typePair, Expression sourceExpr) { var options = mapper.Options; - var sourceName = typePair.SourceType.GetDiscriminatorName(); - var targetName = typePair.TargetType.GetDiscriminatorName(); + typePair.SourceType.GetDiscriminator(out var sourceName, out var sourceValues); + typePair.TargetType.GetDiscriminator(out var targetName, out var targetValues); if (sourceName != targetName) { - throw new MapperException($"Discriminator members '{typePair.SourceType}.{sourceName}' and '{typePair.TargetType}.{targetName}' doesn't match."); + throw new MapperException($"Discriminator members '{typePair.SourceType}.{sourceName}' and '{typePair.TargetType}.{targetName}' doesn't match."); } var member = typePair.GetMember(sourceName); @@ -35,17 +35,14 @@ public Expression Bind(Mapper mapper, TypePair typePair, Expression sourceExpr) throw new MapperException($"Discriminator member '{sourceName}' must be mapped for both {typePair.SourceType} and {typePair.TargetType}"); } - var sourceValues = typePair.SourceType.GetDiscriminatorValues(); - var targetValues = typePair.TargetType.GetDiscriminatorValues(); - var propertyExpr = member.SourceMember.BuildGetExpression(sourceExpr, null); Expression resultExpr = Constant(null, typePair.TargetType.ClrType); - + foreach (var entry in sourceValues) { var sourceValue = entry.Key; - + if (!targetValues.TryGetValue(sourceValue, out Type targetClrType)) { throw new MapperException($"Value '{sourceValue}' for discriminator '{sourceName}' doesn't have an concrete type for '{typePair.TargetType.ClrType}'"); @@ -57,7 +54,7 @@ public Expression Bind(Mapper mapper, TypePair typePair, Expression sourceExpr) var binder = mapper.GetTypeBinder(concreteTypePair); var conditionExpr = Equal(propertyExpr, Constant(sourceValue, sourceValue.GetType())); - + var bindExpr = binder.Bind(mapper, concreteTypePair, Convert(sourceExpr, sourceType.ClrType)); resultExpr = Condition(conditionExpr, Convert(bindExpr, typePair.TargetType.ClrType), resultExpr); diff --git a/src/Detached.Mappers/TypeMappers/Entity/Collection/EntityCollectionTypeMapperFactory.cs b/src/Detached.Mappers/TypeMappers/Entity/Collection/EntityCollectionTypeMapperFactory.cs index 9b8a52b5..e09e4141 100644 --- a/src/Detached.Mappers/TypeMappers/Entity/Collection/EntityCollectionTypeMapperFactory.cs +++ b/src/Detached.Mappers/TypeMappers/Entity/Collection/EntityCollectionTypeMapperFactory.cs @@ -11,9 +11,9 @@ public class EntityCollectionTypeMapperFactory : ITypeMapperFactory public bool CanCreate(Mapper mapper, TypePair typePair) { if (typePair.SourceType.IsCollection() - && !typePair.SourceType.Annotations.Abstract().Value() + && !typePair.SourceType.IsAbstract() && typePair.TargetType.IsCollection() - && !typePair.TargetType.Annotations.Abstract().Value()) + && !typePair.TargetType.IsAbstract()) { IType sourceItemType = mapper.Options.GetType(typePair.TargetType.ItemClrType); IType targetItemType = mapper.Options.GetType(typePair.TargetType.ItemClrType); diff --git a/src/Detached.Mappers/TypeMappers/POCO/Abstract/AbstractTypeMapperFactory.cs b/src/Detached.Mappers/TypeMappers/POCO/Abstract/AbstractTypeMapperFactory.cs index 69330d60..6ab0af93 100644 --- a/src/Detached.Mappers/TypeMappers/POCO/Abstract/AbstractTypeMapperFactory.cs +++ b/src/Detached.Mappers/TypeMappers/POCO/Abstract/AbstractTypeMapperFactory.cs @@ -9,14 +9,14 @@ public class AbstractTypeMapperFactory : ITypeMapperFactory { public bool CanCreate(Mapper mapper, TypePair typePair) { - return typePair.SourceType.Annotations.Abstract().Value() || typePair.TargetType.Annotations.Abstract().Value(); + return typePair.SourceType.IsAbstract() || typePair.TargetType.IsAbstract(); } public ITypeMapper Create(Mapper mapper, TypePair typePair) { Type mapperType = typeof(AbstractTypeMapper<,>).MakeGenericType(typePair.SourceType.ClrType, typePair.TargetType.ClrType); - Type concreteTargetType = typePair.TargetType.Annotations.Abstract().Value() && !typePair.TargetType.IsInherited() && typePair.TargetType.ClrType != typeof(object) + Type concreteTargetType = typePair.TargetType.IsAbstract() && !typePair.TargetType.IsInherited() && typePair.TargetType.ClrType != typeof(object) ? GetConcreteType(mapper.Options, typePair.TargetType.ClrType) : typePair.TargetType.ClrType; diff --git a/src/Detached.Mappers/TypeMappers/POCO/Inherited/InheritedTypeMapperFactory.cs b/src/Detached.Mappers/TypeMappers/POCO/Inherited/InheritedTypeMapperFactory.cs index 10881648..b2ab58fd 100644 --- a/src/Detached.Mappers/TypeMappers/POCO/Inherited/InheritedTypeMapperFactory.cs +++ b/src/Detached.Mappers/TypeMappers/POCO/Inherited/InheritedTypeMapperFactory.cs @@ -15,14 +15,14 @@ public class InheritedTypeMapperFactory : ITypeMapperFactory { public bool CanCreate(Mapper mapper, TypePair typePair) { - return ((typePair.SourceType.IsComplex() || typePair.SourceType.IsEntity()) && !typePair.SourceType.Annotations.Abstract().Value()) + return ((typePair.SourceType.IsComplex() || typePair.SourceType.IsEntity()) && !typePair.SourceType.IsAbstract()) && (typePair.TargetType.IsComplex() || typePair.TargetType.IsEntity()) && typePair.TargetType.IsInherited(); } public ITypeMapper Create(Mapper mapper, TypePair typePair) { - string targetMemberName = typePair.TargetType.GetDiscriminatorName(); + typePair.TargetType.GetDiscriminator(out var targetMemberName, out var targetValues); if (!typePair.Members.TryGetValue(targetMemberName, out TypePairMember member) || member.IsIgnored() || member.SourceMember == null) { @@ -34,7 +34,7 @@ public ITypeMapper Create(Mapper mapper, TypePair typePair) ITypeMember discriminatorMember = typePair.SourceType.GetMember(sourceMemberName); if (discriminatorMember == null) { - throw new MapperException($"Discriminator member {typePair.TargetType.GetDiscriminatorName()} does not exist in type {typePair.TargetType.ClrType}"); + throw new MapperException($"Discriminator member {targetMemberName} does not exist in type {typePair.TargetType.ClrType}"); } var getDiscriminator = @@ -48,7 +48,7 @@ public ITypeMapper Create(Mapper mapper, TypePair typePair) Type tableType = typeof(Dictionary<,>).MakeGenericType(discriminatorMember.ClrType, typeof(ITypeMapper)); IDictionary table = (IDictionary)Activator.CreateInstance(tableType); - foreach (var entry in typePair.TargetType.GetDiscriminatorValues()) + foreach (var entry in targetValues) { IType sourceDiscriminatorType = typePair.SourceType; IType targetDiscriminatorType = mapper.Options.GetType(entry.Value); diff --git a/src/Detached.Mappers/Types/Class/Builder/ClassTypeBuilder.cs b/src/Detached.Mappers/Types/Class/Builder/ClassTypeBuilder.cs index 2a94c79a..ab9a4cd5 100644 --- a/src/Detached.Mappers/Types/Class/Builder/ClassTypeBuilder.cs +++ b/src/Detached.Mappers/Types/Class/Builder/ClassTypeBuilder.cs @@ -82,7 +82,7 @@ public ClassTypeBuilder IncludePrimitives() public ClassTypeDiscriminatorBuilder Discriminator(Expression> selector) { ClassTypeMember memberOptions = GetMember(selector); - Type.SetDiscriminatorName(memberOptions.Name); + Type.Annotations.DiscriminatorName().Set(memberOptions.Name); return new ClassTypeDiscriminatorBuilder(Type); } diff --git a/src/Detached.Mappers/Types/Class/Builder/ClassTypeDiscriminatorBuilder.cs b/src/Detached.Mappers/Types/Class/Builder/ClassTypeDiscriminatorBuilder.cs index 7249a16f..1a3d0a1f 100644 --- a/src/Detached.Mappers/Types/Class/Builder/ClassTypeDiscriminatorBuilder.cs +++ b/src/Detached.Mappers/Types/Class/Builder/ClassTypeDiscriminatorBuilder.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Detached.Mappers.Types.Class.Builder { @@ -13,7 +14,16 @@ public ClassTypeDiscriminatorBuilder(ClassType typeOptions) public ClassTypeDiscriminatorBuilder HasValue(TMember value, Type instantiationType) { - TypeOptions.GetDiscriminatorValues()[value] = instantiationType; + var annotation = TypeOptions.Annotations.DiscriminatorValues(); + + if (annotation.IsDefined()) + { + annotation.Value()[value] = instantiationType; + } + else + { + annotation.Set(new Dictionary { { value, instantiationType } }); + } return this; } diff --git a/src/Detached.Mappers/Types/Class/ClassTypeFactory.cs b/src/Detached.Mappers/Types/Class/ClassTypeFactory.cs index 1e741f7b..03b66dea 100644 --- a/src/Detached.Mappers/Types/Class/ClassTypeFactory.cs +++ b/src/Detached.Mappers/Types/Class/ClassTypeFactory.cs @@ -54,7 +54,7 @@ public virtual IType Create(MapperOptions options, Type clrType) protected virtual void CreateConstructor(ClassType classType) { ConstructorInfo constructorInfo = Array.Find(classType.ClrType.GetConstructors(), c => c.GetParameters().Length == 0); - if (!classType.Annotations.Abstract().Value() && constructorInfo != null) + if (!classType.IsAbstract() && constructorInfo != null) { classType.Constructor = Lambda(New(constructorInfo)); } diff --git a/src/Detached.Mappers/Types/TypeExtensions.cs b/src/Detached.Mappers/Types/TypeExtensions.cs index 64968df6..2d764489 100644 --- a/src/Detached.Mappers/Types/TypeExtensions.cs +++ b/src/Detached.Mappers/Types/TypeExtensions.cs @@ -94,7 +94,7 @@ public static bool IsNullable(this IType type) public static bool IsConcrete(this IType type) { - return !(type.Annotations.Abstract().Value() || type.IsInherited()); + return !(type.IsAbstract() || type.IsInherited()); } } } \ No newline at end of file diff --git a/test/Detached.Mappers.Annotation.Tests/Detached.Mappers.Annotation.Tests.csproj b/test/Detached.Mappers.Annotation.Tests/Detached.Mappers.Annotation.Tests.csproj deleted file mode 100644 index eb24703a..00000000 --- a/test/Detached.Mappers.Annotation.Tests/Detached.Mappers.Annotation.Tests.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - net8.0 - enable - enable - false - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - diff --git a/test/Detached.Mappers.Tests/Annotations/AnnotationTests.cs b/test/Detached.Mappers.Tests/Annotations/AnnotationTests.cs new file mode 100644 index 00000000..a4dde916 --- /dev/null +++ b/test/Detached.Mappers.Tests/Annotations/AnnotationTests.cs @@ -0,0 +1,33 @@ +using Detached.Mappers.Annotations; +using Xunit; + +namespace Detached.Mappers.Annotation.Tests +{ + public class AnnotationTests + { + [Fact] + public void Annotation_Set() + { + var collection = new AnnotationCollection(); + + var annotation = collection.Annotation("TEST_ANNOTATION"); + + Assert.False(annotation.IsDefined()); + + annotation.Set(true); + + Assert.True(annotation.IsDefined()); + Assert.True(annotation.Value()); + + annotation.Set(false); + + Assert.True(annotation.IsDefined()); + Assert.False(annotation.Value()); + + annotation.Reset(); + + Assert.False(annotation.IsDefined()); + Assert.False(annotation.Value()); + } + } +} \ No newline at end of file diff --git a/test/Detached.Mappers.Tests/Annotations/TypeAnnotationTests.cs b/test/Detached.Mappers.Tests/Annotations/TypeAnnotationTests.cs new file mode 100644 index 00000000..ed53f651 --- /dev/null +++ b/test/Detached.Mappers.Tests/Annotations/TypeAnnotationTests.cs @@ -0,0 +1,183 @@ +using Detached.Mappers.Exceptions; +using Detached.Mappers.Types; +using Detached.Mappers.Types.Class; +using System; +using System.Collections.Generic; +using Xunit; + +namespace Detached.Mappers.Tests.Annotations +{ + public class TypeAnnotationTests + { + [Fact] + public void Annotation_Abstract() + { + IType type = new ClassType(); + + type.Abstract(true); + + Assert.True(type.Annotations.Abstract().IsDefined()); + Assert.True(type.IsAbstract()); + + type.Abstract(false); + + Assert.True(type.Annotations.Abstract().IsDefined()); + Assert.False(type.IsAbstract()); + + type.Annotations.Abstract().Reset(); + + Assert.False(type.Annotations.Abstract().IsDefined()); + Assert.False(type.IsAbstract()); + } + + [Fact] + public void Annotation_Entity() + { + ClassType type = new ClassType(); + type.MappingSchema = MappingSchema.Complex; + + type.Entity(true); + + Assert.True(type.Annotations.Entity().IsDefined()); + Assert.True(type.IsEntity()); + + type.Entity(false); + + Assert.True(type.Annotations.Entity().IsDefined()); + Assert.False(type.IsEntity()); + + type.Annotations.Entity().Reset(); + + Assert.False(type.Annotations.Entity().IsDefined()); + Assert.False(type.IsEntity()); + + type.MappingSchema = MappingSchema.Primitive; + + Assert.Throws(() => type.Entity()); + } + + [Fact] + public void Annotation_Key() + { + ClassTypeMember member = new ClassTypeMember(); + + member.Key(true); + + Assert.True(member.Annotations.Key().IsDefined()); + Assert.True(member.IsKey()); + + member.Key(false); + + Assert.True(member.Annotations.Key().IsDefined()); + Assert.False(member.IsKey()); + + member.Annotations.Key().Reset(); + + Assert.False(member.Annotations.Key().IsDefined()); + Assert.False(member.IsKey()); + } + + [Fact] + public void Annotation_MapIgnore() + { + ClassTypeMember member = new ClassTypeMember(); + + member.Ignore(true); + + Assert.True(member.Annotations.Ignored().IsDefined()); + Assert.True(member.IsIgnored()); + + member.Ignore(false); + + Assert.True(member.Annotations.Ignored().IsDefined()); + Assert.False(member.IsIgnored()); + + member.Annotations.Ignored().Reset(); + + Assert.False(member.Annotations.Ignored().IsDefined()); + Assert.False(member.IsIgnored()); + } + + [Fact] + public void Annotation_Parent() + { + ClassTypeMember member = new ClassTypeMember(); + + member.Parent(true); + + Assert.True(member.Annotations.Parent().IsDefined()); + Assert.True(member.IsParent()); + + member.Parent(false); + + Assert.True(member.Annotations.Parent().IsDefined()); + Assert.False(member.IsParent()); + + member.Annotations.Parent().Reset(); + + Assert.False(member.Annotations.Parent().IsDefined()); + Assert.False(member.IsParent()); + } + + [Fact] + public void Annotation_Primitive() + { + ClassTypeMember member = new ClassTypeMember(); + + member.Primitive(true); + + Assert.True(member.Annotations.Primitive().IsDefined()); + Assert.True(member.IsSetAsPrimitive()); + + member.Primitive(false); + + Assert.True(member.Annotations.Primitive().IsDefined()); + Assert.False(member.IsSetAsPrimitive()); + + member.Annotations.Primitive().Reset(); + + Assert.False(member.Annotations.Primitive().IsDefined()); + Assert.False(member.IsSetAsPrimitive()); + } + + [Fact] + public void Annotation_Discriminator() + { + IType type = new ClassType(); + + type.SetDiscriminator("SOME_PROP", new Dictionary + { + { "a", typeof(int) }, + { "b", typeof(string) } + }); + + Assert.True(type.Annotations.DiscriminatorName().IsDefined()); + Assert.True(type.Annotations.DiscriminatorValues().IsDefined()); + + var result = type.GetDiscriminator(out var setName, out var setValues); + + Assert.True(result); + + Assert.Equal("SOME_PROP", setName); + Assert.NotNull(setValues); + + Assert.Equal(typeof(int), setValues["a"]); + Assert.Equal(typeof(string), setValues["b"]); + } + + + [Fact] + public void Annotation_ConcurrencyToken() + { + IType type = new ClassType(); + + type.SetConcurrencyTokenName("SOME_PROP"); + + Assert.True(type.Annotations.ConcurrencyTokenName().IsDefined()); + + string token = type.GetConcurrencyTokenName(); + + Assert.Equal("SOME_PROP", token); + } + } +} diff --git a/test/Detached.Mappers.Tests/Annotations/TypePairAnnotationTests.cs b/test/Detached.Mappers.Tests/Annotations/TypePairAnnotationTests.cs new file mode 100644 index 00000000..3d72fffe --- /dev/null +++ b/test/Detached.Mappers.Tests/Annotations/TypePairAnnotationTests.cs @@ -0,0 +1,6 @@ +namespace Detached.Mappers.Tests.Annotations +{ + public class TypePairAnnotationTests + { + } +}