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