Можно ли переопределить атрибут DataAnnotation в дочернем классе .NET?

Я пытаюсь переопределить DataAnnotation в дочернем классе.

Я пробовал решения по аналогичным вопросам, но у меня был ограниченный успех.

Например, у меня есть этот класс, использующий RangeAttribute

public class BaseViewModel 
{
    [Range(1, 99999999, ErrorMessageResourceName = "NotInRange9M", ErrorMessageResourceType = typeof(Resources.Account))]
    public virtual decimal? Amount { get; set; }
}

и дочерний класс:

public class ExtendedViewModel : BaseViewModel
{
    internal decimal? _amount;

    [Range(1, 2000, ErrorMessageResourceName = "NotInRange2K", ErrorMessageResourceType = typeof(Resources.Account))]
    public override decimal? Amount {
        get { return _amount; }
        set { _amount = value; }
    }
}

Этот пример работает, поэтому форма, в которой используется первый объект, выдаст ошибку проверки на стороне клиента "The amount must be between 1 and 999,999,999", а вторая — "The amount must be between 1 and 2,000".

Однако, если я хочу иметь дочерний класс вообще без какой-либо проверки:

public class ExtendedViewModel : BaseViewModel
{
    internal decimal? _amount;

    public override decimal? Amount {
        get { return _amount; }
        set { _amount = value; }
    }
}

Форма, использующая это, по-прежнему будет выдавать ошибку проверки на стороне клиента "The amount must be between 1 and 999,999,999", которую она каким-то образом наследует от родителя.

Значит, мы можем переопределить атрибуты, но не можем от них избавиться? Есть ли другой способ?

Я также пробовал:

    new public decimal? Amount {
        get { return _amount; }
        set { _amount = value; }
    }

безуспешно.

Мне пришлось обойти это ограничение, но я хочу понять этот механизм аннотаций данных, чтобы лучше их использовать.


person Nick    schedule 02.04.2014    source источник


Ответы (1)


Ну, есть AttributeUsageAttribute... в классах Attributes.

Например, RangeAttribute выглядит так

[AttributeUsage(AttributeTargets.Property|AttributeTargets.Field|AttributeTargets.Parameter, AllowMultiple = false)]
public class RangeAttribute : ValidationAttribute

Одним из свойств класса AttributeUsageAttribute является Inherited, который выглядит так.

    //
    // Summary:
    //     Gets or sets a Boolean value indicating whether the indicated attribute can
    //     be inherited by derived classes and overriding members.
    //
    // Returns:
    //     true if the attribute can be inherited by derived classes and overriding
    //     members; otherwise, false. The default is true.
    public bool Inherited { get; set; }

Итак, как мы видели в определении RangeAttribute, свойство Inherited не присутствует в атрибуте. Так что по умолчанию это правда, поэтому атрибут наследуется при переопределении членов.

person Raphaël Althaus    schedule 02.04.2014
comment
Хорошо. Как мы переопределяем свойство Inherited как false внутри дочернего класса? - person Nick; 02.04.2014
comment
Вы не можете! Вам нужно будет создать собственный атрибут без наследования. - person Raphaël Althaus; 02.04.2014
comment
Да, но вместо того, чтобы декомпилировать System.ComponentModel.DataAnnotations.RangeAttribute и копировать весь код в новый атрибут с Inheritance=false, можно ли расширить его и отключить наследование? - person Nick; 02.04.2014
comment
@Nick, но в этом случае вы никогда не унаследуете (на любой дочерней модели просмотра). Кстати, наследование ViewModel обычно (моя точка зрения, конечно) плохая идея. - person Raphaël Althaus; 02.04.2014
comment
Я хочу использовать атрибут RangeWithoutInheritance только для одной конкретной модели представления. - person Nick; 02.04.2014
comment
@Nick, вы можете попытаться создать RangeWithoutInheritance , наследуя от RangeAttribute, и изменить значение свойства Inherited. Честно говоря, не уверен, что произойдет ;) Но это должно работать. - person Raphaël Althaus; 02.04.2014
comment
Это не сработало :( В любом случае, я приму это как ответ, потому что это кажется невозможным - person Nick; 02.04.2014