Browse Source

#3979: Allow to set custom "default value" for extra properties.

pull/3985/head
Halil İbrahim Kalkan 6 years ago
parent
commit
2cd8311792
  1. 38
      docs/en/Object-Extensions.md
  2. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyDto.cs
  3. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs
  4. 9
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/HasExtraPropertiesExtensions.cs
  5. 16
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensionPropertyHelper.cs
  6. 20
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs
  7. 2
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs
  8. 20
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs
  9. 50
      framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/ObjectExtensionManager_Tests.cs

38
docs/en/Object-Extensions.md

@ -174,6 +174,44 @@ ObjectExtensionManager.Instance
The following sections explain the fundamental property configuration options.
#### Default Value
A default value is automatically set for the new property, which is the natural default value for the property type, like `null` for `string`, `false` for `bool` or `0` for `int`.
There are two ways to override the default value:
##### DefaultValue Option
`DefaultValue` option can be set to any value:
````csharp
ObjectExtensionManager.Instance
.AddOrUpdateProperty<IdentityUser, int>(
"MyIntProperty",
options =>
{
options.DefaultValue = 42;
});
````
##### DefaultValueFactory Options
`DefaultValueFactory` can be set to a function that returns the default value:
````csharp
ObjectExtensionManager.Instance
.AddOrUpdateProperty<IdentityUser, int>(
"MyIntProperty",
options =>
{
options.DefaultValueFactory = () => 42;
});
````
`options.DefaultValueFactory` has a higher priority than the `options.DefaultValue` .
> Tip: Use `DefaultValueFactory` option only if the default value may change over the time. If it is a constant value, then use the `DefaultValue` option.
#### CheckPairDefinitionOnMapping
Controls how to check property definitions while mapping two extensible objects. See the "Object to Object Mapping" section to understand the `CheckPairDefinitionOnMapping` option better.

2
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyDto.cs

@ -21,5 +21,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending
public List<ExtensionPropertyAttributeDto> Attributes { get; set; }
public Dictionary<string, object> Configuration { get; set; }
public object DefaultValue { get; set; }
}
}

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs

@ -108,6 +108,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending
Attributes = new List<ExtensionPropertyAttributeDto>(),
DisplayName = CreateDisplayNameDto(propertyConfig),
Configuration = new Dictionary<string, object>(),
DefaultValue = propertyConfig.GetDefaultValue(),
Api = new ExtensionPropertyApiDto
{
OnGet = new ExtensionPropertyApiGetDto

9
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/HasExtraPropertiesExtensions.cs

@ -65,8 +65,13 @@ namespace Volo.Abp.Data
public static TSource SetDefaultsForExtraProperties<TSource>(this TSource source, Type objectType = null)
where TSource : IHasExtraProperties
{
if (objectType == null)
{
objectType = typeof(TSource);
}
var properties = ObjectExtensionManager.Instance
.GetProperties(objectType ?? typeof(TSource));
.GetProperties(objectType);
foreach (var property in properties)
{
@ -75,7 +80,7 @@ namespace Volo.Abp.Data
continue;
}
source.ExtraProperties[property.Name] = TypeHelper.GetDefaultValue(property.Type);
source.ExtraProperties[property.Name] = property.GetDefaultValue();
}
return source;

16
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensionPropertyHelper.cs

@ -5,7 +5,7 @@ using Volo.Abp.Reflection;
namespace Volo.Abp.ObjectExtending
{
public static class ExtensionPropertyHelper
internal static class ExtensionPropertyHelper
{
public static IEnumerable<Attribute> GetDefaultAttributes(Type type)
{
@ -19,5 +19,19 @@ namespace Volo.Abp.ObjectExtending
yield return new EnumDataTypeAttribute(type);
}
}
public static object GetDefaultValue(
Type propertyType,
Func<object> defaultValueFactory,
object defaultValue)
{
if (defaultValueFactory != null)
{
return defaultValueFactory();
}
return defaultValue ??
TypeHelper.GetDefaultValue(propertyType);
}
}
}

20
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Localization;
using Volo.Abp.Reflection;
namespace Volo.Abp.ObjectExtending.Modularity
{
@ -45,6 +46,19 @@ namespace Volo.Abp.ObjectExtending.Modularity
[NotNull]
public ExtensionPropertyApiConfiguration Api { get; }
/// <summary>
/// Uses as the default value if <see cref="DefaultValueFactory"/> was not set.
/// </summary>
[CanBeNull]
public object DefaultValue { get; set; }
/// <summary>
/// Used with the first priority to create the default value for the property.
/// Uses to the <see cref="DefaultValue"/> if this was not set.
/// </summary>
[CanBeNull]
public Func<object> DefaultValueFactory { get; set; }
public ExtensionPropertyConfiguration(
[NotNull] EntityExtensionConfiguration entityExtensionConfiguration,
[NotNull] Type type,
@ -63,6 +77,12 @@ namespace Volo.Abp.ObjectExtending.Modularity
Api = new ExtensionPropertyApiConfiguration();
Attributes.AddRange(ExtensionPropertyHelper.GetDefaultAttributes(Type));
DefaultValue = TypeHelper.GetDefaultValue(Type);
}
public object GetDefaultValue()
{
return ExtensionPropertyHelper.GetDefaultValue(Type, DefaultValueFactory, DefaultValue);
}
}
}

2
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs

@ -152,6 +152,8 @@ namespace Volo.Abp.ObjectExtending.Modularity
property.Attributes.AddRange(propertyConfig.Attributes);
property.DisplayName = propertyConfig.DisplayName;
property.Validators.AddRange(propertyConfig.Validators);
property.DefaultValue = propertyConfig.DefaultValue;
property.DefaultValueFactory = propertyConfig.DefaultValueFactory;
}
);
}

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

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using JetBrains.Annotations;
using Volo.Abp.Localization;
using Volo.Abp.Reflection;
namespace Volo.Abp.ObjectExtending
{
@ -47,6 +48,19 @@ namespace Volo.Abp.ObjectExtending
[NotNull]
public Dictionary<object, object> Configuration { get; }
/// <summary>
/// Uses as the default value if <see cref="DefaultValueFactory"/> was not set.
/// </summary>
[CanBeNull]
public object DefaultValue { get; set; }
/// <summary>
/// Used with the first priority to create the default value for the property.
/// Uses to the <see cref="DefaultValue"/> if this was not set.
/// </summary>
[CanBeNull]
public Func<object> DefaultValueFactory { get; set; }
public ObjectExtensionPropertyInfo(
[NotNull] ObjectExtensionInfo objectExtension,
[NotNull] Type type,
@ -62,6 +76,12 @@ namespace Volo.Abp.ObjectExtending
Validators = new List<Action<ObjectExtensionPropertyValidationContext>>();
Attributes.AddRange(ExtensionPropertyHelper.GetDefaultAttributes(Type));
DefaultValue = TypeHelper.GetDefaultValue(Type);
}
public object GetDefaultValue()
{
return ExtensionPropertyHelper.GetDefaultValue(Type, DefaultValueFactory, DefaultValue);
}
}
}

50
framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/ObjectExtensionManager_Tests.cs

@ -119,6 +119,56 @@ namespace Volo.Abp.ObjectExtending
.ShouldNotContain(x => x is RequiredAttribute);
}
[Fact]
public void Should_Set_DefaultValues()
{
_objectExtensionManager
.AddOrUpdateProperty<MyExtensibleObject, int>("IntProp")
.AddOrUpdateProperty<MyExtensibleObject, int>("IntPropWithCustomDefaultValue", property =>
{
property.DefaultValue = 42;
})
.AddOrUpdateProperty<MyExtensibleObject, bool>("BoolProp")
.AddOrUpdateProperty<MyExtensibleObject, int?>("NullableIntProp")
.AddOrUpdateProperty<MyExtensibleObject, int?>("NullableIntPropWithCustomDefaultValueFactory", property =>
{
property.DefaultValueFactory = () => 2;
})
.AddOrUpdateProperty<MyExtensibleObject, string>("StringProp")
.AddOrUpdateProperty<MyExtensibleObject, string>("StringPropWithCustomDefaultValue", property =>
{
property.DefaultValue = "custom-value";
});
_objectExtensionManager
.GetPropertyOrNull<MyExtensibleObject>("IntProp")
.DefaultValue.ShouldBe(0);
_objectExtensionManager
.GetPropertyOrNull<MyExtensibleObject>("IntPropWithCustomDefaultValue")
.DefaultValue.ShouldBe(42);
_objectExtensionManager
.GetPropertyOrNull<MyExtensibleObject>("BoolProp")
.DefaultValue.ShouldBe(false);
_objectExtensionManager
.GetPropertyOrNull<MyExtensibleObject>("NullableIntProp")
.DefaultValue.ShouldBeNull();
var propWithDefaultValueFactory = _objectExtensionManager
.GetPropertyOrNull<MyExtensibleObject>("NullableIntPropWithCustomDefaultValueFactory");
propWithDefaultValueFactory.GetDefaultValue().ShouldBe(2);
_objectExtensionManager
.GetPropertyOrNull<MyExtensibleObject>("StringProp")
.DefaultValue.ShouldBeNull();
_objectExtensionManager
.GetPropertyOrNull<MyExtensibleObject>("StringPropWithCustomDefaultValue")
.DefaultValue.ShouldBe("custom-value");
}
private class MyExtensibleObject : ExtensibleObject
{

Loading…
Cancel
Save