定制特性可以应用的目标元素可以为:程序集(assembly)、模块(module)、类型(type)、属性(property)、事件(event)、字段(field)、方法(method)、参数(param)、返回值(return)
定制特性以[,]形式展现,放在紧挨着的元素上,多个特性可以应用于同一元素,特性间以逗号隔开,以下表达规则有效:
[AttributeUsage][ Flags]、[AttributeUsage, Flags]、[Flags, AttibuteUsageAttribute]、[AttributeUsage(), FlagesAttribute()]
attibute实例,是在编译期进行初始化,而不是运行的时候。
定制特性类型,必须直接或者间接的继承自System.Attribute类,而且该类型必须有公有构造函数来创建其实例。
所有自定义的特性名称都应该有个Attribute后缀,这是习惯性约定。
定制特性也可以应用在其他定制特性上,这点也很好理解,因为定制特性本身也是一个类,遵守类的公有规则。例如很多时候我们的自定义定制特性会应用AttributeUsageAttribute特性,来控制如何应用新定义的特性。
[AttributeUsageAttribute(AttributeTarget.All), [AttributeUsageAttribute(AttributeTarget.All), AllowMultiple = true, Inherited = true] class MyNewAttribute: System.Attribute { // }
定制特性不会影响应用元素的任何功能,只是约定了该元素具有的特质。
所有非抽象特性必须具有public访问限制。
定制特性常用于在运行期获得代码注释信息,以附加信息来优化调试。
定制特性可以应用在某些设计模式中,如工厂模式。
定制特性还常用于位标记,非托管函数标记、方法废弃标记等其他方面。
特性能干嘛
1)功能性信息:如[Serializable]加在类前表示该类可被串行化。
[Serializable]
public class HumanProperty
2)提示性信息:如[Obsolete]表示该方法已经过时,提醒程序员使用新的替代函数。
[Obsolete("Use another method : Average(), instead!", true)]
public virtual void CalcAverage(int speed)
3)限定性信息:如[Conditional("DEBUG")]表示下面的方法只有在调试模式下才有效。
[Conditional("DEBUG")]
public void UnitTest()
4)描述性信息:如[Description]对所指对象进行详细描述。
public enum CreditCardType
{
[Description("Unknown")]
Unknown,
[Description("Corp Card")]
CC
}
可以定义一个特性用来验证用户是否登录
/// <summary> /// 用户登陆的过滤器,没有登陆的用户将跳到/User/Login页面 /// </summary> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public sealed class LoginAuthorizeAttribute : ActionFilterAttribute//ActionFilterAttribute是MVC中定义的一个特性 { //对ActionFilterAttribute特性中的方法进行重写 public override void OnActionExecuting(ActionExecutingContext filterContext) { ///ViewsHelper.userInfo ///ViewsHelper是一个静态类,用来存放一些全局的数据,登录数据,用户信息等 ///userInfo是ViewsHelper中的用户登录数据 if (ViewsHelper.userInfo == null) { //发现没有用户登录信息设置重定向地址和参数 filterContext.Result = new RedirectResult( string.Concat("/UserInfo/Login" , "?returnUrl=" , filterContext.RequestContext .HttpContext .Server .UrlEncode(filterContext.HttpContext.Request.Url.PathAndQuery))); } else { var model = LoginSessionHelper.GetLoginSession(ViewsHelper.userInfo.ID); if (model != null) { if (model.SessionID != filterContext.HttpContext.Session.SessionID) { filterContext.HttpContext.Session.Clear(); filterContext.Result = new RedirectResult( string.Concat("/UserInfo/Login" , "?tag=1&time=" + model.LastTime.ToString("HH:mm:dd") + "&returnUrl=" , filterContext.RequestContext .HttpContext .Server .UrlEncode(filterContext.HttpContext.Request.Url.PathAndQuery))); } } } base.OnActionExecuting(filterContext); } }
可以对类或者属性等等,添加描述信息
public enum AdvertisementType { [Description("视频")] Video = 1, [Description("图片")] Image = 2 }
然后就可以通过反射来获取到每个枚举中定义的Description("视频") 属性