如何使用反射获取属性名称或获取当前验证的数据属性的属性信息?涉及IT技术。

5

我希望编写自定义验证属性,并将具有验证错误的其他成员名称添加到验证结果中。问题在于,我想根据属性名称和无效匹配属性索引或键(我想验证IEnumerables或IDictionaries)动态生成成员名称,例如Names [0] ,Names [1] ,Names [key] 等。例如:

模型:

public class ModelClass
{
    [ItemMaxLength(10)]
    [Display(ResourceType = typeof(CategoriesRename), Name = "CategoryNamesFieldName")]
    public IDictionary<string, string> Names { get; set; }
}

属性:

public class ItemMaxLengthAttribute : ValidationAttribute
{
    private readonly int _maxLength = int.MaxValue;

    public ItemMaxLengthAttribute(int maxLength)
    {
        _maxLength = maxLength;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        ...
        // I can get instance and it's type from validation context
        var instance = validationContext.ObjectInstance; // which is instance of ModelClass
        var instanceType = validationContext.ObjectType; //which is typeof(ModelClass)
        var dispayName = validationContext.DisplayName; //which is value of Display attribute
        ...
    }
}

所以主要的想法是(我也不喜欢它)通过它的 DysplayName 属性值 (dispayName) 来验证当前属性。我一直卡在这里。也许有其他方法可以获取正在验证的属性的属性信息吗?

P.S. 我已经尝试过 MemberName 属性,就像Alexandre Rondeau建议的那样,但问题是 validationContext.MemberName = null ,所以无法使用。此外,MSDN说,此属性表示实体成员名称,而不是相应数据字段的名称,而我需要相应数据字段的名称


  1. 在您的示例“ModelClass”中,“[ItemMaxLength]”未应用于“Names”属性。您在哪里应用验证属性?
  2. 当您在该示例中说“相应数据字段的名称”时,那个名称是什么?它不是“Names”吗?
- Alexandre Rondeau
@AlexandreRondeau,1)我已经将属性应用于“Names”属性(可能只是忘记在示例中演示它了)。2)是的,它是_Names_... 应该是...但是validationContext.MemberName为空。所以我有一些麻烦来获取_Names_。 - Dmytro
2个回答

4
使用该代码,两个测试都通过了,因此MemberName不是空值。
[TestClass]
public class RefectionInValidationTest
{
    [TestMethod]
    public void GivenAModelWithItemMaxAttributeOnFieldName_WhenValidating_ThenModelClassIsValid()
    {
        //Arange
        var validModelClass = new ModelClass();
        var validations = new Collection<ValidationResult>();

        //Act
        var isValid = Validator.TryValidateObject(validModelClass, new ValidationContext(validModelClass, null, null), validations, true);

        //Assert
        Assert.IsTrue(isValid);
    }

    [TestMethod]
    public void GivenAModelWithItemMaxAttributeOnFieldNotName_WhenValidating_ThenModelClassIsInvalid()
    {
        //Arange
        var invalidaModelClass = new InvalidModelClass();
        var validations = new Collection<ValidationResult>();

        //Act
        var isValid = Validator.TryValidateObject(invalidaModelClass, new ValidationContext(invalidaModelClass, null, null), validations, true);

        //Assert
        Assert.IsFalse(isValid);
    }
}

public class ModelClass
{
    [ItemMaxLength(10)]
    public IDictionary<string, string> Names { get; set; }
}
public class InvalidModelClass
{
    [ItemMaxLength(10)]
    public IDictionary<string, string> NotNames { get; set; }
}

public class ItemMaxLengthAttribute : ValidationAttribute
{
    private readonly int _maxLength = int.MaxValue;

    public ItemMaxLengthAttribute(int maxLength)
    {
        _maxLength = maxLength;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var propretyInfo = validationContext.ObjectType.GetProperty(validationContext.MemberName);
        if (propretyInfo.Name == "Names")
            return ValidationResult.Success;

        return new ValidationResult("The property isn't 'Names'");
    }
}

validationContext.MemberName 为空,因此它会抛出 ArgumentNullException - Dmytro
我已经发布了我的测试类代码,包括所有的类。你能否运行这两个测试并告诉我它们在你的系统上是否通过。 - Alexandre Rondeau

0

您需要使用validationContext.MemberName属性。

例如:

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
        var userManager = validationContext.GetService<UserManager<ApplicationUser>>();
        
        var findingTask = userManager.FindByEmailAsync((string)value);
        findingTask.Wait();

        var user = findingTask.Result;

        return user == null
                ? ValidationResult.Success
                : new ValidationResult("This email already in use", new string[] { validationContext.MemberName });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接