Browse Source

Refactor ObjectExtending.

pull/3401/head
Halil İbrahim Kalkan 7 years ago
parent
commit
edf8f82fc2
  1. 2
      framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperExtensibleDtoExtensions.cs
  2. 7
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs
  3. 91
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs
  4. 2
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/MappingPropertyDefinitionChecks.cs
  5. 11
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs
  6. 11
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManager.cs
  7. 9
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs
  8. 6
      framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs

2
framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperExtensibleDtoExtensions.cs

@ -8,7 +8,7 @@ namespace AutoMapper
{ {
public static IMappingExpression<TSource, TDestination> MapExtraProperties<TSource, TDestination>( public static IMappingExpression<TSource, TDestination> MapExtraProperties<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> mappingExpression, this IMappingExpression<TSource, TDestination> mappingExpression,
MappingPropertyDefinitionCheck definitionCheck = MappingPropertyDefinitionCheck.Both) MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both)
where TDestination : IHasExtraProperties where TDestination : IHasExtraProperties
where TSource : IHasExtraProperties where TSource : IHasExtraProperties
{ {

7
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs

@ -69,14 +69,17 @@ namespace Volo.Abp.EntityFrameworkCore.Modeling
} }
public static void ConfigureObjectExtensions<T>(this EntityTypeBuilder<T> b) public static void ConfigureObjectExtensions<T>(this EntityTypeBuilder<T> b)
where T : class where T : class, IHasExtraProperties
{ {
b.As<EntityTypeBuilder>().TryConfigureObjectExtensions(); b.As<EntityTypeBuilder>().TryConfigureObjectExtensions();
} }
public static void TryConfigureObjectExtensions(this EntityTypeBuilder b) public static void TryConfigureObjectExtensions(this EntityTypeBuilder b)
{ {
ObjectExtensionManager.Instance.ConfigureEfCoreEntity(b); if (b.Metadata.ClrType.IsAssignableTo<IHasExtraProperties>())
{
ObjectExtensionManager.Instance.ConfigureEfCoreEntity(b);
}
} }
public static void ConfigureSoftDelete<T>(this EntityTypeBuilder<T> b) public static void ConfigureSoftDelete<T>(this EntityTypeBuilder<T> b)

91
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using JetBrains.Annotations;
using Volo.Abp.Data; using Volo.Abp.Data;
namespace Volo.Abp.ObjectExtending namespace Volo.Abp.ObjectExtending
@ -11,26 +13,31 @@ namespace Volo.Abp.ObjectExtending
/// to the <paramref name="destination"/> object. /// to the <paramref name="destination"/> object.
/// ///
/// Checks property definitions (over the <see cref="ObjectExtensionManager"/>) /// Checks property definitions (over the <see cref="ObjectExtensionManager"/>)
/// based on the <paramref name="definitionCheck"/> preference. /// based on the <paramref name="definitionChecks"/> preference.
/// </summary> /// </summary>
/// <typeparam name="TSource">Source class type</typeparam> /// <typeparam name="TSource">Source class type</typeparam>
/// <typeparam name="TDestination">Destination class type</typeparam> /// <typeparam name="TDestination">Destination class type</typeparam>
/// <param name="source">The source object</param> /// <param name="source">The source object</param>
/// <param name="destination">The destination object</param> /// <param name="destination">The destination object</param>
/// <param name="definitionCheck"> /// <param name="definitionChecks">
/// Controls which properties to map. /// Controls which properties to map.
/// </param> /// </param>
public static void MapExtraPropertiesTo<TSource, TDestination>( public static void MapExtraPropertiesTo<TSource, TDestination>(
this TSource source, [NotNull] this TSource source,
TDestination destination, [NotNull] TDestination destination,
MappingPropertyDefinitionCheck definitionCheck = MappingPropertyDefinitionCheck.Both) MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both)
where TSource : IHasExtraProperties where TSource : IHasExtraProperties
where TDestination : IHasExtraProperties where TDestination : IHasExtraProperties
{ {
MapExtraPropertiesTo<TSource, TDestination>( Check.NotNull(source, nameof(source));
Check.NotNull(destination, nameof(destination));
MapExtraPropertiesTo(
typeof(TSource),
typeof(TDestination),
source.ExtraProperties, source.ExtraProperties,
destination.ExtraProperties, destination.ExtraProperties,
definitionCheck definitionChecks
); );
} }
@ -39,45 +46,82 @@ namespace Volo.Abp.ObjectExtending
/// to the <paramref name="destinationDictionary"/> object. /// to the <paramref name="destinationDictionary"/> object.
/// ///
/// Checks property definitions (over the <see cref="ObjectExtensionManager"/>) /// Checks property definitions (over the <see cref="ObjectExtensionManager"/>)
/// based on the <paramref name="definitionCheck"/> preference. /// based on the <paramref name="definitionChecks"/> preference.
/// </summary> /// </summary>
/// <typeparam name="TSource">Source class type (for definition check)</typeparam> /// <typeparam name="TSource">Source class type (for definition check)</typeparam>
/// <typeparam name="TDestination">Destination class type (for definition check)</typeparam> /// <typeparam name="TDestination">Destination class type (for definition check)</typeparam>
/// <param name="sourceDictionary">The source dictionary object</param> /// <param name="sourceDictionary">The source dictionary object</param>
/// <param name="destinationDictionary">The destination dictionary object</param> /// <param name="destinationDictionary">The destination dictionary object</param>
/// <param name="definitionCheck"> /// <param name="definitionChecks">
/// Controls which properties to map. /// Controls which properties to map.
/// </param> /// </param>
public static void MapExtraPropertiesTo<TSource, TDestination>( public static void MapExtraPropertiesTo<TSource, TDestination>(
Dictionary<string, object> sourceDictionary, [NotNull] Dictionary<string, object> sourceDictionary,
Dictionary<string, object> destinationDictionary, [NotNull] Dictionary<string, object> destinationDictionary,
MappingPropertyDefinitionCheck definitionCheck = MappingPropertyDefinitionCheck.Both) MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both)
where TSource : IHasExtraProperties where TSource : IHasExtraProperties
where TDestination : IHasExtraProperties where TDestination : IHasExtraProperties
{ {
var sourceObjectExtension = ObjectExtensionManager.Instance.GetOrNull<TSource>(); MapExtraPropertiesTo(
if (definitionCheck.HasFlag(MappingPropertyDefinitionCheck.Source) && typeof(TSource),
typeof(TDestination),
sourceDictionary,
destinationDictionary,
definitionChecks
);
}
/// <summary>
/// Copies extra properties from the <paramref name="sourceDictionary"/> object
/// to the <paramref name="destinationDictionary"/> object.
///
/// Checks property definitions (over the <see cref="ObjectExtensionManager"/>)
/// based on the <paramref name="definitionChecks"/> preference.
/// </summary>
/// <param name="sourceType">Source type (for definition check)</param>
/// <param name="destinationType">Destination class type (for definition check)</param>
/// <param name="sourceDictionary">The source dictionary object</param>
/// <param name="destinationDictionary">The destination dictionary object</param>
/// <param name="definitionChecks">
/// Controls which properties to map.
/// </param>
public static void MapExtraPropertiesTo(
[NotNull] Type sourceType,
[NotNull] Type destinationType,
[NotNull] Dictionary<string, object> sourceDictionary,
[NotNull] Dictionary<string, object> destinationDictionary,
MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both)
{
Check.AssignableTo<IHasExtraProperties>(sourceType, nameof(sourceType));
Check.AssignableTo<IHasExtraProperties>(destinationType, nameof(destinationType));
Check.NotNull(sourceDictionary, nameof(sourceDictionary));
Check.NotNull(destinationDictionary, nameof(destinationDictionary));
var sourceObjectExtension = ObjectExtensionManager.Instance.GetOrNull(sourceType);
if (definitionChecks.HasFlag(MappingPropertyDefinitionChecks.Source) &&
sourceObjectExtension == null) sourceObjectExtension == null)
{ {
return; return;
} }
var destinationObjectExtension = ObjectExtensionManager.Instance.GetOrNull<TDestination>(); var destinationObjectExtension = ObjectExtensionManager.Instance.GetOrNull(destinationType);
if (definitionCheck.HasFlag(MappingPropertyDefinitionCheck.Destination) && if (definitionChecks.HasFlag(MappingPropertyDefinitionChecks.Destination) &&
destinationObjectExtension == null) destinationObjectExtension == null)
{ {
return; return;
} }
if (definitionCheck == MappingPropertyDefinitionCheck.None) if (definitionChecks == MappingPropertyDefinitionChecks.None)
{ {
foreach (var keyValue in sourceDictionary) foreach (var keyValue in sourceDictionary)
{ {
destinationDictionary[keyValue.Key] = keyValue.Value; destinationDictionary[keyValue.Key] = keyValue.Value;
} }
} }
else if (definitionCheck == MappingPropertyDefinitionCheck.Source) else if (definitionChecks == MappingPropertyDefinitionChecks.Source)
{ {
Debug.Assert(sourceObjectExtension != null, nameof(sourceObjectExtension) + " != null");
foreach (var property in sourceObjectExtension.GetProperties()) foreach (var property in sourceObjectExtension.GetProperties())
{ {
if (!sourceDictionary.ContainsKey(property.Name)) if (!sourceDictionary.ContainsKey(property.Name))
@ -88,8 +132,10 @@ namespace Volo.Abp.ObjectExtending
destinationDictionary[property.Name] = sourceDictionary[property.Name]; destinationDictionary[property.Name] = sourceDictionary[property.Name];
} }
} }
else if (definitionCheck == MappingPropertyDefinitionCheck.Destination) else if (definitionChecks == MappingPropertyDefinitionChecks.Destination)
{ {
Debug.Assert(destinationObjectExtension != null, nameof(destinationObjectExtension) + " != null");
foreach (var keyValue in sourceDictionary) foreach (var keyValue in sourceDictionary)
{ {
if (!destinationObjectExtension.HasProperty(keyValue.Key)) if (!destinationObjectExtension.HasProperty(keyValue.Key))
@ -100,8 +146,11 @@ namespace Volo.Abp.ObjectExtending
destinationDictionary[keyValue.Key] = keyValue.Value; destinationDictionary[keyValue.Key] = keyValue.Value;
} }
} }
else if (definitionCheck == MappingPropertyDefinitionCheck.Both) else if (definitionChecks == MappingPropertyDefinitionChecks.Both)
{ {
Debug.Assert(sourceObjectExtension != null, nameof(sourceObjectExtension) + " != null");
Debug.Assert(destinationObjectExtension != null, nameof(destinationObjectExtension) + " != null");
foreach (var property in sourceObjectExtension.GetProperties()) foreach (var property in sourceObjectExtension.GetProperties())
{ {
if (!sourceDictionary.ContainsKey(property.Name)) if (!sourceDictionary.ContainsKey(property.Name))
@ -119,7 +168,7 @@ namespace Volo.Abp.ObjectExtending
} }
else else
{ {
throw new NotImplementedException(definitionCheck + " was not implemented!"); throw new NotImplementedException(definitionChecks + " was not implemented!");
} }
} }
} }

2
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/MappingPropertyDefinitionCheck.cs → framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/MappingPropertyDefinitionChecks.cs

@ -3,7 +3,7 @@
namespace Volo.Abp.ObjectExtending namespace Volo.Abp.ObjectExtending
{ {
[Flags] [Flags]
public enum MappingPropertyDefinitionCheck : byte public enum MappingPropertyDefinitionChecks : byte
{ {
/// <summary> /// <summary>
/// No check. Copy all extra properties from the source to the destination. /// No check. Copy all extra properties from the source to the destination.

11
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs

@ -2,20 +2,24 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using JetBrains.Annotations; using JetBrains.Annotations;
using Volo.Abp.Data;
namespace Volo.Abp.ObjectExtending namespace Volo.Abp.ObjectExtending
{ {
public class ObjectExtensionInfo public class ObjectExtensionInfo
{ {
[NotNull]
public Type Type { get; } public Type Type { get; }
[NotNull]
protected Dictionary<string, ObjectExtensionPropertyInfo> Properties { get; } protected Dictionary<string, ObjectExtensionPropertyInfo> Properties { get; }
[NotNull]
public Dictionary<object, object> Configuration { get; } public Dictionary<object, object> Configuration { get; }
public ObjectExtensionInfo(Type type) public ObjectExtensionInfo([NotNull] Type type)
{ {
Type = type; Type = Check.AssignableTo<IHasExtraProperties>(type, nameof(type));
Properties = new Dictionary<string, ObjectExtensionPropertyInfo>(); Properties = new Dictionary<string, ObjectExtensionPropertyInfo>();
Configuration = new Dictionary<object, object>(); Configuration = new Dictionary<object, object>();
} }
@ -25,6 +29,7 @@ namespace Volo.Abp.ObjectExtending
return Properties.ContainsKey(propertyName); return Properties.ContainsKey(propertyName);
} }
[NotNull]
public virtual ObjectExtensionInfo AddOrUpdateProperty<TProperty>( public virtual ObjectExtensionInfo AddOrUpdateProperty<TProperty>(
[NotNull] string propertyName, [NotNull] string propertyName,
[CanBeNull] Action<ObjectExtensionPropertyInfo> configureAction = null) [CanBeNull] Action<ObjectExtensionPropertyInfo> configureAction = null)
@ -36,6 +41,7 @@ namespace Volo.Abp.ObjectExtending
); );
} }
[NotNull]
public virtual ObjectExtensionInfo AddOrUpdateProperty( public virtual ObjectExtensionInfo AddOrUpdateProperty(
[NotNull] Type propertyType, [NotNull] Type propertyType,
[NotNull] string propertyName, [NotNull] string propertyName,
@ -54,6 +60,7 @@ namespace Volo.Abp.ObjectExtending
return this; return this;
} }
[NotNull]
public virtual ImmutableList<ObjectExtensionPropertyInfo> GetProperties() public virtual ImmutableList<ObjectExtensionPropertyInfo> GetProperties()
{ {
return Properties.Values.ToImmutableList(); return Properties.Values.ToImmutableList();

11
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManager.cs

@ -16,6 +16,7 @@ namespace Volo.Abp.ObjectExtending
ObjectsExtensions = new Dictionary<Type, ObjectExtensionInfo>(); ObjectsExtensions = new Dictionary<Type, ObjectExtensionInfo>();
} }
[NotNull]
public virtual ObjectExtensionManager AddOrUpdate<TObject>( public virtual ObjectExtensionManager AddOrUpdate<TObject>(
[CanBeNull] Action<ObjectExtensionInfo> configureAction = null) [CanBeNull] Action<ObjectExtensionInfo> configureAction = null)
where TObject : IHasExtraProperties where TObject : IHasExtraProperties
@ -23,12 +24,13 @@ namespace Volo.Abp.ObjectExtending
return AddOrUpdate(typeof(TObject), configureAction); return AddOrUpdate(typeof(TObject), configureAction);
} }
[NotNull]
public virtual ObjectExtensionManager AddOrUpdate( public virtual ObjectExtensionManager AddOrUpdate(
[NotNull] Type type, [NotNull] Type type,
[CanBeNull] Action<ObjectExtensionInfo> configureAction = null) [CanBeNull] Action<ObjectExtensionInfo> configureAction = null)
{ {
Check.NotNull(type, nameof(type)); Check.AssignableTo<IHasExtraProperties>(type, nameof(type));
var extensionInfo = ObjectsExtensions.GetOrAdd( var extensionInfo = ObjectsExtensions.GetOrAdd(
type, type,
() => new ObjectExtensionInfo(type) () => new ObjectExtensionInfo(type)
@ -39,14 +41,17 @@ namespace Volo.Abp.ObjectExtending
return this; return this;
} }
[CanBeNull]
public virtual ObjectExtensionInfo GetOrNull<TObject>() public virtual ObjectExtensionInfo GetOrNull<TObject>()
where TObject : IHasExtraProperties
{ {
return GetOrNull(typeof(TObject)); return GetOrNull(typeof(TObject));
} }
[CanBeNull]
public virtual ObjectExtensionInfo GetOrNull([NotNull] Type type) public virtual ObjectExtensionInfo GetOrNull([NotNull] Type type)
{ {
Check.NotNull(type, nameof(type)); Check.AssignableTo<IHasExtraProperties>(type, nameof(type));
return ObjectsExtensions.GetOrDefault(type); return ObjectsExtensions.GetOrDefault(type);
} }

9
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs

@ -15,19 +15,18 @@ namespace Volo.Abp.ObjectExtending
[NotNull] [NotNull]
public Type Type { get; } public Type Type { get; }
//[NotNull] //TODO: Will be implemented, probably in the v2.5
//public List<ValidationAttribute> ValidationAttributes { get; }
[NotNull] [NotNull]
public Dictionary<object, object> Configuration { get; } public Dictionary<object, object> Configuration { get; }
public ObjectExtensionPropertyInfo([NotNull] ObjectExtensionInfo objectExtension, [NotNull] Type type, [NotNull] string name) public ObjectExtensionPropertyInfo(
[NotNull] ObjectExtensionInfo objectExtension,
[NotNull] Type type,
[NotNull] string name)
{ {
ObjectExtension = Check.NotNull(objectExtension, nameof(objectExtension)); ObjectExtension = Check.NotNull(objectExtension, nameof(objectExtension));
Type = Check.NotNull(type, nameof(type)); Type = Check.NotNull(type, nameof(type));
Name = Check.NotNull(name, nameof(name)); Name = Check.NotNull(name, nameof(name));
//ValidationAttributes = new List<ValidationAttribute>();
Configuration = new Dictionary<object, object>(); Configuration = new Dictionary<object, object>();
} }
} }

6
framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs

@ -37,7 +37,7 @@ namespace Volo.Abp.ObjectExtending
[Fact] [Fact]
public void MapExtraPropertiesTo_Should_Only_Map_Source_Defined_Properties_If_Requested() public void MapExtraPropertiesTo_Should_Only_Map_Source_Defined_Properties_If_Requested()
{ {
_person.MapExtraPropertiesTo(_personDto, MappingPropertyDefinitionCheck.Source); _person.MapExtraPropertiesTo(_personDto, MappingPropertyDefinitionChecks.Source);
_personDto.GetProperty<string>("Name").ShouldBe("John"); //Defined in both classes _personDto.GetProperty<string>("Name").ShouldBe("John"); //Defined in both classes
_personDto.GetProperty<int>("Age").ShouldBe(42); //Defined in source _personDto.GetProperty<int>("Age").ShouldBe(42); //Defined in source
@ -49,7 +49,7 @@ namespace Volo.Abp.ObjectExtending
[Fact] [Fact]
public void MapExtraPropertiesTo_Should_Only_Map_Destination_Defined_Properties_If_Requested() public void MapExtraPropertiesTo_Should_Only_Map_Destination_Defined_Properties_If_Requested()
{ {
_person.MapExtraPropertiesTo(_personDto, MappingPropertyDefinitionCheck.Destination); _person.MapExtraPropertiesTo(_personDto, MappingPropertyDefinitionChecks.Destination);
_personDto.GetProperty<string>("Name").ShouldBe("John"); //Defined in both classes _personDto.GetProperty<string>("Name").ShouldBe("John"); //Defined in both classes
_personDto.GetProperty<int>("ChildCount").ShouldBe(2); //Defined in destination _personDto.GetProperty<int>("ChildCount").ShouldBe(2); //Defined in destination
@ -61,7 +61,7 @@ namespace Volo.Abp.ObjectExtending
[Fact] [Fact]
public void MapExtraPropertiesTo_Should_Copy_all_With_No_Property_Definition_Check() public void MapExtraPropertiesTo_Should_Copy_all_With_No_Property_Definition_Check()
{ {
_person.MapExtraPropertiesTo(_personDto, MappingPropertyDefinitionCheck.None); _person.MapExtraPropertiesTo(_personDto, MappingPropertyDefinitionChecks.None);
_personDto.GetProperty<string>("Name").ShouldBe("John"); _personDto.GetProperty<string>("Name").ShouldBe("John");
_personDto.GetProperty<int>("Age").ShouldBe(42); _personDto.GetProperty<int>("Age").ShouldBe(42);

Loading…
Cancel
Save