C# 在MVC5中重写属性时,属性的继承是如何工作的?

C# 在MVC5中重写属性时,属性的继承是如何工作的?,c#,jquery,asp.net-mvc,inheritance,attributes,C#,Jquery,Asp.net Mvc,Inheritance,Attributes,我希望在基类中装饰某些虚拟属性,从基类继承,重写属性并用其他属性装饰(例如,有时显示名称不同,或者需要字段),并且基类中的属性仍然适用 这可能吗 下面是我尝试做的一个例子: public class MySSN { [InputMask("999-99-9999")] //NOT available in the list of attributes! [Display(Name = "Social Security Number")] //NOT available in th

我希望在基类中装饰某些虚拟属性,从基类继承,重写属性并用其他属性装饰(例如,有时显示名称不同,或者需要字段),并且基类中的属性仍然适用

这可能吗

下面是我尝试做的一个例子:

public class MySSN
{
    [InputMask("999-99-9999")] //NOT available in the list of attributes!
    [Display(Name = "Social Security Number")] //NOT available in the list of attributes!
    public virtual string TheSSN { get; set; } = string.Empty;
}

public class SocialSecurityNumber : MySSN
{
    [Required] //Available in the list of attributes!
    public override string TheSSN { get; set; } = string.Empty;
}

public class PersonModel
{
    //...
    public SocialSecurityNumber SSN { get; set; } = new SocialSecurityNumber();

    //...
}
编辑:

@model Models.PersonModel
@using MyHTMLExtensions

<div class="row">
    <div class="col-sm-4">
        @Html.DLAPTextBoxFor(m => m.SSN.TheSSN, new { style = "max-width: 200px;" })
    </div>
</div>
@model Models.PersonModel
@使用MyHtmlex
@Html.DLAPTextBoxFor(m=>m.SSN.TheSSN,新的{style=“max width:200px;”})
输入掩码属性: 注意:当我的自定义控件检索元数据时,OnMetadataCreated()会正确激发!但是,它不是控件的全名。它只是继承类“SocialSecurityNumber()”中的基础“TheSSN”名称。问题的关键是,我需要在这里使用控件的全名,但我理解,因为元数据是在了解任何有关模型的信息之前触发的,所以在这个级别上是不可能的

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class InputMaskAttribute : Attribute, IMetadataAware
{
    private string _mask = string.Empty;
    private string _placeHolder = string.Empty;

    public InputMaskAttribute(string mask, string placeHolder = "")
    {
        _mask = mask;
        if (!string.IsNullOrEmpty(placeHolder))
        {
            _placeHolder = string.Format(",{{placeholder:\"{0}\"}}", placeHolder);
        }
    }

    public string Mask
    {
        get { return _mask; }
    }

    public string PlaceHolder
    {
        get { return _placeHolder; }
    }

    private const string ScriptText = "<script type='text/javascript'>" +
                                        "$(document).ready(function () {{" +
                                        "$('#{0}').mask('{1}'{2});}});</script>";


    public const string templateHint = "_mask";     // Causes _mask.cshtml to be used

    private int _count;

    //public string Id
    //{
    //    //get { return "PhoneNumber"; }
    //    get { return "maskedInput_" + _count; }
    //}

    internal HttpContextBase Context
    {
        get { return new HttpContextWrapper(HttpContext.Current); }
    }

    public void CreateMask(ModelMetadata metadata, string PropertyName)
    {
        string Id = PropertyName;
        string key = string.Format("InputMask_{0}", Id);
        if (!Context.Items.Contains(key))
        {
            //Only do this if the key is not already present
            var list = Context.Items["Scripts"] as IList<string> ?? new List<string>();
            _count = list.Count;
            metadata.TemplateHint = templateHint;
            metadata.AdditionalValues[templateHint] = Id;
            string scriptToAdd = string.Format(ScriptText, Id, Mask, PlaceHolder);
            list.Add(scriptToAdd);
            Context.Items["Scripts"] = list;
            Context.Items.Add(key, scriptToAdd);
        }
    }
    //USING the special TEXTBOXFOR to handle this in most cases.
    public void OnMetadataCreated(ModelMetadata metadata)
    {
        CreateMask(metadata, metadata.PropertyName);
    }
}
[AttributeUsage(AttributeTargets.Property,AllowMultiple=true,Inherited=true)]
公共类InputMaskaAttribute:属性,IMetadataAware
{
私有字符串_mask=string.Empty;
私有字符串_占位符=string.Empty;
公共输入maskattribute(字符串掩码,字符串占位符=)
{
_面具=面具;
如果(!string.IsNullOrEmpty(占位符))
{
_占位符=string.Format(“,{{占位符:\”{0}\“}”,占位符);
}
}
公共字符串掩码
{
获取{return\u mask;}
}
公共字符串占位符
{
获取{return\u占位符;}
}
private const string ScriptText=“”+
“$(文档).ready(函数(){{”+
“$('{0}')。掩码('{1}'{2});}}};”;
public const string templateHint=“\u mask”//导致使用\u mask.cshtml
私人国际单位计数;
//公共字符串Id
//{
////获取{返回“电话号码”;}
//获取{return“maskedInput”+\u count;}
//}
内部HttpContextBase上下文
{
获取{返回新的HttpContextWrapper(HttpContext.Current);}
}
公共void CreateMask(ModelMetadata元数据,字符串PropertyName)
{
字符串Id=PropertyName;
string key=string.Format(“InputMask_{0}”,Id);
如果(!Context.Items.Contains(key))
{
//仅当密钥不存在时才执行此操作
var list=Context.Items[“Scripts”]作为IList??new list();
_count=list.count;
metadata.TemplateHint=TemplateHint;
metadata.AdditionalValues[templateHint]=Id;
string scriptToAdd=string.Format(脚本文本、Id、掩码、占位符);
list.Add(scriptToAdd);
Context.Items[“Scripts”]=列表;
Context.Items.Add(key,scriptToAdd);
}
}
//在大多数情况下,使用特殊的TEXTBOXFOR来处理此问题。
已创建元数据(ModelMetadata元数据)上的公共void
{
CreateMask(元数据,metadata.PropertyName);
}
}
在HTMLExtensions类中,我的自定义文本框: 我可以通过检查自定义属性并在此处创建第二个具有控件全名的jQuery脚本来解决OnMetadataCreated没有给我全名的问题。但是,只有当InputAttribute修饰继承成员的重写时,这才起作用。换句话说,我无法在此处读取基本成员的属性(SocialSecurityNumber.MySSN.TheSSN-“[InputMask]”和“[Display]”属性),只能读取继承成员的属性(SocialSecurityNumber.TheSSN-“[Required]”属性)

我知道基本属性正在生效,因为显示名称显示正确,并且在获取元数据时,“OnMetadataCreated()”正确触发(只是名称错误)。因此,属性是正确继承的

那么它们在属性列表中的什么位置

namespace MyHTMLExtensions
{
public static class HtmlExtensions
{
    internal static MvcHtmlString DLAPTextBoxFor<TModel, TValue>(
        this HtmlHelper<TModel> html,
        Expression<Func<TModel, TValue>> expression,
        IDictionary<string, object> htmlAttributes = null,
        bool readOnly = false)
    {
        if (htmlAttributes == null)
        {
            htmlAttributes = new Dictionary<string, object>();
        }

        ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

        //Check for special InputMaskAttribute
        //ONLY FINDS THE "[Required]" ATTRIBUTE, BUT  NOT THE BASE ATTRIBUTES.  HOW DO I GET THE BASE ATTRIBUTES THAT ARE INHERITED???  I know they are inherited properly because the Display value shows properly on the page!
        InputMaskAttribute testAtt = GetModelAttribute<InputMaskAttribute>(modelMetadata, false);
        if (testAtt != null)
        {
            //Get the FULL ID of the control (might be nested) to use in the jQuery that will create for the control
            string fullControlID = html.IdFor(expression).ToString();
            testAtt.CreateMask(modelMetadata, fullControlID);
        }
    //........
    }

    internal static TAttribute GetModelAttribute<TAttribute>(ModelMetadata modelMetadata, bool inherit) where TAttribute : Attribute
    {
        if (modelMetadata == null) throw new ArgumentException("modelMetadata");
        var containerType = modelMetadata.ContainerType;

        TAttribute attribute = null;
        if (containerType != null)
        {
            //When overriding a base class property decorated with attributes, the base attributes are not in the list - only the overriding property attributes are listed.
            //object[] allAttributes = containerType.GetProperty(modelMetadata.PropertyName).GetCustomAttributes(inherit);
            TAttribute[] attributes = ((TAttribute[])
                containerType.GetProperty(modelMetadata.PropertyName).GetCustomAttributes(typeof(TAttribute), inherit));

            attribute = attributes.FirstOrDefault();
        }

        return attribute;
    }
}
namespace myhtmlex
{
公共静态类
{
内部静态MvcHtmlString DLAPTextBoxFor(
这个HtmlHelper html,
表情表情,
IDictionary HtmlatAttributes=null,
bool readOnly=false)
{
如果(htmlAttributes==null)
{
htmlAttributes=新字典();
}
ModelMetadata ModelMetadata=ModelMetadata.FromLambdaExpression(表达式,html.ViewData);
//检查是否存在特殊输入maskattribute
//只查找“[必需]”属性,而不查找基本属性。如何获取继承的基本属性???我知道它们被正确继承,因为显示值在页面上正确显示!
InputMaskAttribute testAtt=GetModelAttribute(modelMetadata,false);
if(testAtt!=null)
{
//获取要在将为控件创建的jQuery中使用的控件的完整ID(可能是嵌套的)
字符串fullControlID=html.IdFor(expression.ToString();
CreateMask(modelMetadata,fullControlID);
}
//........
}
内部静态TatAttribute GetModelAttribute(ModelMetadata ModelMetadata,bool inherit),其中TatAttribute:Attribute
{
如果(modelMetadata==null)抛出新的ArgumentException(“modelMetadata”);
var containerType=modelMetadata.containerType;
tatAttribute属性=null;
if(containerType!=null)
{
//重写用属性修饰的基类属性时,基类属性不在列表中-仅列出重写属性属性。
//对象[]allAttributes=containerType.GetProperty(modelMetadata.PropertyName).GetCustomAttributes(inherit);
TatAttribute[]属性=((TatAttribute[]))
containerType.GetProperty(modelMetadata.PropertyName).Get