mirror of https://github.com/abpframework/abp.git
10 changed files with 231 additions and 99 deletions
@ -0,0 +1,75 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DynamicProxy; |
|||
|
|||
namespace Volo.Abp.ObjectExtending |
|||
{ |
|||
public static class ExtensibleObjectValidator |
|||
{ |
|||
[NotNull] |
|||
public static List<ValidationResult> GetValidationErrors( |
|||
[NotNull] IHasExtraProperties extensibleObject, |
|||
[CanBeNull] IServiceProvider serviceProvider = null) |
|||
{ |
|||
var validationErrors = new List<ValidationResult>(); |
|||
|
|||
AddValidationErrors( |
|||
extensibleObject, |
|||
new ValidationContext( |
|||
extensibleObject, |
|||
serviceProvider, |
|||
new Dictionary<object, object>() |
|||
), |
|||
validationErrors |
|||
); |
|||
|
|||
return validationErrors; |
|||
} |
|||
|
|||
public static void AddValidationErrors( |
|||
[NotNull] IHasExtraProperties extensibleObject, |
|||
[NotNull] ValidationContext validationContext, |
|||
[NotNull] List<ValidationResult> validationErrors) |
|||
{ |
|||
Check.NotNull(extensibleObject, nameof(extensibleObject)); |
|||
Check.NotNull(validationContext, nameof(validationContext)); |
|||
Check.NotNull(validationErrors, nameof(validationErrors)); |
|||
|
|||
var objectType = ProxyHelper.UnProxy(extensibleObject).GetType(); |
|||
|
|||
var objectExtensionInfo = ObjectExtensionManager.Instance |
|||
.GetOrNull(objectType); |
|||
|
|||
if (objectExtensionInfo == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
foreach (var propertyInfo in objectExtensionInfo.GetProperties()) |
|||
{ |
|||
if (propertyInfo.ValidationAttributes.IsNullOrEmpty()) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var validationContext2 = new ValidationContext(extensibleObject, validationContext, null) |
|||
{ |
|||
DisplayName = propertyInfo.Name, |
|||
MemberName = propertyInfo.Name |
|||
}; |
|||
|
|||
foreach (var attribute in propertyInfo.ValidationAttributes) |
|||
{ |
|||
var result = attribute.GetValidationResult(extensibleObject.GetProperty(propertyInfo.Name), validationContext2); |
|||
if (result != null) |
|||
{ |
|||
validationErrors.Add(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,68 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.ObjectExtending |
|||
{ |
|||
public static class ObjectExtensionPropertyInfoValidationExtensions |
|||
{ |
|||
public const string ValidationConfigurationName = "Validation"; |
|||
|
|||
[NotNull] |
|||
public static ObjectExtensionPropertyInfo ConfigureValidation( |
|||
[NotNull] this ObjectExtensionPropertyInfo propertyExtension, |
|||
[NotNull] Action<ObjectExtensionPropertyInfoValidationOptions> configureAction) |
|||
{ |
|||
Check.NotNull(propertyExtension, nameof(propertyExtension)); |
|||
Check.NotNull(configureAction, nameof(configureAction)); |
|||
|
|||
configureAction(propertyExtension.GetOrAddValidationConfiguration()); |
|||
|
|||
return propertyExtension; |
|||
} |
|||
|
|||
[NotNull] |
|||
public static ObjectExtensionPropertyInfo AddValidationAttributes( |
|||
[NotNull] this ObjectExtensionPropertyInfo propertyExtension, |
|||
[NotNull] params ValidationAttribute[] validationAttributes) |
|||
{ |
|||
Check.NotNull(propertyExtension, nameof(propertyExtension)); |
|||
Check.NotNullOrEmpty(validationAttributes, nameof(validationAttributes)); |
|||
|
|||
propertyExtension |
|||
.GetOrAddValidationConfiguration() |
|||
.ValidationAttributes |
|||
.AddRange(validationAttributes); |
|||
|
|||
return propertyExtension; |
|||
} |
|||
|
|||
[CanBeNull] |
|||
public static ObjectExtensionPropertyInfoValidationOptions GetValidationConfigurationOrNull( |
|||
[NotNull] this ObjectExtensionPropertyInfo propertyExtension) |
|||
{ |
|||
Check.NotNull(propertyExtension, nameof(propertyExtension)); |
|||
|
|||
return propertyExtension.Configuration.GetOrDefault(ValidationConfigurationName) |
|||
as ObjectExtensionPropertyInfoValidationOptions; |
|||
} |
|||
|
|||
[NotNull] |
|||
public static ObjectExtensionPropertyInfoValidationOptions GetOrAddValidationConfiguration( |
|||
[NotNull] this ObjectExtensionPropertyInfo propertyExtension) |
|||
{ |
|||
Check.NotNull(propertyExtension, nameof(propertyExtension)); |
|||
|
|||
var validationConfiguration = propertyExtension.GetValidationConfigurationOrNull(); |
|||
|
|||
if (validationConfiguration == null) |
|||
{ |
|||
validationConfiguration = new ObjectExtensionPropertyInfoValidationOptions(propertyExtension); |
|||
propertyExtension.Configuration[ValidationConfigurationName] = validationConfiguration; |
|||
} |
|||
|
|||
return validationConfiguration; |
|||
} |
|||
} |
|||
} |
|||
@ -1,25 +0,0 @@ |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.ObjectExtending |
|||
{ |
|||
public class ObjectExtensionPropertyInfoValidationOptions |
|||
{ |
|||
[NotNull] |
|||
public ObjectExtensionPropertyInfo ExtensionProperty { get; } |
|||
|
|||
[NotNull] |
|||
public ObjectExtensionInfo ObjectExtension => ExtensionProperty.ObjectExtension; |
|||
|
|||
[NotNull] |
|||
public List<ValidationAttribute> ValidationAttributes { get; } |
|||
|
|||
public ObjectExtensionPropertyInfoValidationOptions( |
|||
[NotNull] ObjectExtensionPropertyInfo extensionProperty) |
|||
{ |
|||
ExtensionProperty = Check.NotNull(extensionProperty, nameof(extensionProperty)); |
|||
ValidationAttributes = new List<ValidationAttribute>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,109 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Shouldly; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Threading; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.ObjectExtending |
|||
{ |
|||
public class ExtensibleObjectValidator_Tests |
|||
{ |
|||
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); |
|||
|
|||
static ExtensibleObjectValidator_Tests() |
|||
{ |
|||
OneTimeRunner.Run(() => |
|||
{ |
|||
ObjectExtensionManager.Instance |
|||
.AddOrUpdate<ExtensiblePersonObject>(options => |
|||
{ |
|||
options.AddOrUpdateProperty<string>("Name", propertyInfo => |
|||
{ |
|||
propertyInfo.ValidationAttributes.Add(new RequiredAttribute()); |
|||
propertyInfo.ValidationAttributes.Add(new StringLengthAttribute(64) { MinimumLength = 2 }); |
|||
}); |
|||
|
|||
options.AddOrUpdateProperty<string>("Address", propertyInfo => |
|||
{ |
|||
propertyInfo.ValidationAttributes.Add(new StringLengthAttribute(255)); |
|||
}); |
|||
|
|||
options.AddOrUpdateProperty<byte>("Age", propertyInfo => |
|||
{ |
|||
propertyInfo.ValidationAttributes.Add(new RequiredAttribute()); |
|||
propertyInfo.ValidationAttributes.Add(new RangeAttribute(18, 99)); |
|||
}); |
|||
|
|||
options.AddOrUpdateProperty<bool>("IsMarried", propertyInfo => |
|||
{ |
|||
|
|||
}); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Validate_If_The_Properties_Are_Valid() |
|||
{ |
|||
ExtensibleObjectValidator |
|||
.GetValidationErrors( |
|||
new ExtensiblePersonObject |
|||
{ |
|||
ExtraProperties = |
|||
{ |
|||
{"Name", "John"}, |
|||
{"Age", "42"}, |
|||
} |
|||
} |
|||
).Count.ShouldBe(0); //All Valid
|
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Not_Validate_If_The_Properties_Are_Not_Valid() |
|||
{ |
|||
ExtensibleObjectValidator |
|||
.GetValidationErrors( |
|||
new ExtensiblePersonObject() |
|||
).Count.ShouldBe(2); //Name & Age
|
|||
|
|||
ExtensibleObjectValidator |
|||
.GetValidationErrors( |
|||
new ExtensiblePersonObject |
|||
{ |
|||
ExtraProperties = |
|||
{ |
|||
{"Address", new string('x', 256) } |
|||
} |
|||
} |
|||
).Count.ShouldBe(3); //Name, Age & Address
|
|||
|
|||
ExtensibleObjectValidator |
|||
.GetValidationErrors( |
|||
new ExtensiblePersonObject |
|||
{ |
|||
ExtraProperties = |
|||
{ |
|||
{"Age", "42" } |
|||
} |
|||
} |
|||
).Count.ShouldBe(1); //Name
|
|||
|
|||
ExtensibleObjectValidator |
|||
.GetValidationErrors( |
|||
new ExtensiblePersonObject |
|||
{ |
|||
ExtraProperties = |
|||
{ |
|||
{"Address", new string('x', 256) }, |
|||
{"Age", "100" } |
|||
} |
|||
} |
|||
).Count.ShouldBe(3); //Name, Age & Address
|
|||
} |
|||
|
|||
private class ExtensiblePersonObject : ExtensibleObject |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue