Възможно ли е да се замени атрибут 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, и да промените стойността на наследеното свойство. Не съм сигурен какво ще се случи, честно казано ;) Но трябва да работи. - person Raphaël Althaus; 02.04.2014
comment
Това не проработи :( Както и да е, ще приема това като отговор, защото изглежда неосъществимо - person Nick; 02.04.2014