gpt4 book ai didi

.net - 字段由同一属性多次注释

转载 作者:行者123 更新时间:2023-12-04 11:51:45 25 4
gpt4 key购买 nike

对于我的ASP.NET MVC应用程序,我创建了自定义验证属性,并指出可以为单个字段或属性指定多个实例:

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
public sealed class SomeAttribute: ValidationAttribute

我已经为此类属性创建了验证器:
public class SomeValidator : DataAnnotationsModelValidator<SomeAttribute>

并将其连接到Global.asax的 Application_Start
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof (SomeAttribute), typeof (SomeValidator));

最后,如果我以期望的方式使用属性:
[SomeAttribute(...)]  //first
[SomeAttribute(...)] //second
public string SomeField { get; set; }

当框架执行验证时,仅调用第一个属性实例。第二个似乎已经死了。我注意到,在每个请求期间,仅创建一个验证器实例(用于第一个注释)。

如何解决这个问题并解雇所有属性?

最佳答案

让我回答我自己。从MSDN(http://msdn.microsoft.com/en-us/library/system.attribute.typeid.aspxhttp://msdn.microsoft.com/en-us/library/6w3a7b50.aspx):

When you define a custom attribute with AttributeUsageAttribute.AllowMultiple set to true, you must override the Attribute.TypeId property to make it unique. If all instances of your attribute are unique, override Attribute.TypeId to return the object identity of your attribute. If only some instances of your attribute are unique, return a value from Attribute.TypeId that would return equality in those cases. For example, some attributes have a constructor parameter that acts as a unique key. For these attributes, return the value of the constructor parameter from the Attribute.TypeId property.

As implemented, this identifier is merely the Type of the attribute. However, it is intended that the unique identifier be used to identify two attributes of the same type.



总结一下:

TypeId被记录为“用于标识相同类型的两个属性的唯一标识符”。默认情况下,TypeId只是属性的类型,因此当遇到相同类型的两个属性时,MVC验证框架会将它们视为“相同”。

实现:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
public sealed class SomeAttribute: ValidationAttribute
{
private string Parameter { get; set; }
public override object TypeId
{
get { return string.Format("{0}[{1}]", GetType().FullName, Parameter); }
}

public SomeAttribute(string parameter)
{
Parameter = parameter;
}

在下面的替代方法中选择了创建TypeId的方式:
  • 返回新对象-太多了,实例总是不同的,
  • 返回基于字符串参数的哈希码-可能导致冲突(无限多个字符串不能通过内射法映射到任何有限集中-字符串的最佳唯一标识符是字符串本身,请参阅here)。

  • 完成后,服务器端验证案例将起作用。当这个想法需要与不打扰的客户端验证相结合时,问题就开始了。假设您已通过以下方式定义了自定义验证器:
    public class SomeAttributeValidator : DataAnnotationsModelValidator<SomeAttribute>
    {
    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
    {
    var rule = new ModelClientValidationRule {ValidationType = "someattribute"};
    rule.ValidationParameters.Add(...)
    yield return rule;
    }

    有这个:
    public class Model
    {
    [SomeAttribute("first")]
    [SomeAttribute("second")]
    public string SomeField { get; set; }

    导致以下错误:

    Validation type names in unobtrusive client validation rules must be unique. The following validation type was seen more than once: someattribute



    如前所述,解决方案是具有唯一的验证类型。我们必须区分已用于注释字段的每个已注册属性实例,并为其提供相应的验证类型:
    public class SomeAttributeValidator : DataAnnotationsModelValidator<SomeAttribute>
    {
    private string AnnotatedField { get; set; }
    public SomeAttributeValidator(
    ModelMetadata metadata, ControllerContext context, SomeAttribute attribute)
    : base(metadata, context, attribute)
    {
    AnnotatedField = string.Format("{0}.{1}",
    metadata.ContainerType.FullName, metadata.PropertyName);
    }

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
    {
    var count = Storage.Get<int>(AnnotatedField) + 1;
    Storage.Set(AnnotatedField, count);

    var suffix = char.ConvertFromUtf32(96 + count); // gets a lowercase letter
    var rule = new ModelClientValidationRule
    {
    ValidationType = string.Format("someattribute{0}", suffix)
    };

    (验证类型必须仅包含小写字母-使用上述解决方案,如果您具有26个以上的属性-整个字母都用尽,则可能会出现异常)

    其中 Storage是简单的实用程序,用于存储当前http请求的数据:
    internal class Storage
    {
    private static IDictionary Items
    {
    get
    {
    if (HttpContext.Current == null)
    throw new ApplicationException("HttpContext not available.");
    return HttpContext.Current.Items;
    }
    }

    public static T Get<T>(string key)
    {
    if (Items[key] == null)
    return default(T);
    return (T)Items[key];
    }

    public static void Set<T>(string key, T value)
    {
    Items[key] = value;
    }
    }

    最后,JavaScript部分:
    $.each('abcdefghijklmnopqrstuvwxyz'.split(''), function(idx, val) {
    var adapter = 'someattribute' + val;
    $.validator.unobtrusive.adapters.add(adapter, [...], function(options) {
    options.rules[adapter] = {
    ...
    };
    if (options.message) {
    options.messages[adapter] = options.message;
    }
    });
    });

    $.each('abcdefghijklmnopqrstuvwxyz'.split(''), function(idx, val) {
    var method = 'someattribute' + val;
    $.validator.addMethod(method, function(value, element, params) {
    ...
    }, '');
    });

    对于完整的解决方案, go through this sources

    关于.net - 字段由同一属性多次注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25414296/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com