特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
特性的使用方法很简单,只需要写在方法,类,枚举,字段等程序体的上面用[]
括起来即可,如下。
[Route("api/[controller]/[action]")]
[ApiController]
public class TestController:ControllerBase
{
[HttpGet]
[Obsolete]
public void Test()
{
Console.WriteLine("这是一个过时的方法");
}
}
一般都支持多个特性。
AttributeUsage
AttributeUsage
仅对继承自Attribute
的派生类有效,目的是控制当前类的使用范围。比如下面这段代码,我定义了一个TestUser
的自定义特性,在AttributeUsage
参数里传入了AttributeTargets.Method
这个参数,指定当前特性仅对方法有效。
[AttributeUsage(AttributeTargets.Method)]
class TestUserAttribute : Attribute
{
public static void Test()
{
}
}
那我当我在使用这个特性的时候。就只能定义在方法的上面。
[TestUser]
static void Main(string[] args)
{
Test();
Console.WriteLine("Hello, World!");
}
如果放到其他的结构上面,则会报错。
如果需要指定对多种程序体有效的话,这里写多个目标,中间用 |
隔开,或者指定AttributeTargets.All
,表示对所有程序体有效。
//仅对方法和类有效
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,AllowMultiple =true)]
class TestUserAttribute : Attribute
{
public static void Test()
{
}
}
//对所有结构有效
[AttributeUsage(AttributeTargets.All,AllowMultiple =true)]
class TestUserAttribute : Attribute
{
public static void Test()
{
}
}
Obsolete
该特性可以用来声明程序体是过时的,被弃用的。
[Obsolete("该方法已过时,请使用TestNew",true)]
static void Test()
{
Console.WriteLine("这是一个被过时的方法");
}
static void TestNew()
{
Console.WriteLine("这是一个最新的方法");
}
Obsolete
有三个重载。
ObsoleteAttribute() 表示该程序体是被弃用的。
ObsoleteAttribute(string? message) 可以输入提示内容,在鼠标移动到程序体名称上时显示。
ObsoleteAttribute(string? message, bool error) bool参数用来表示该方法是否弃用,若为true
,则该程序体不能被使用。默认为false
Conditional
Conditional
位于System.Diagnostics
命名空间下
这个特定通过条件判断决定是否运行下面对应的程序体。比如下面这样,我传了一个字符串Debug
,但是并没有定义这个字符串,那么这个方法就不会执行。
如果在最上面定义了Debug,则这个方法就会执行。
在命名空间 Microsoft.AspNetCore.Mvc
下,有很多定义好的特性,接下来我会挑部分常用的特性做简单介绍。.NET Core 3.1版本。
RouteAttribute
作用域:Class ,Method
说明:使用给定的路由模板创建一个新的。
ApiControllerAttribute
作用域:Assembly,Class
说明:指示使用类型和所有派生类型提供 HTTP API 响应。
HttpGetAttribute
作用域:All
说明:标识支持 HTTP GET 方法的操作。
HttpPostAttribute
作用域:All
说明:标识支持 HTTP POST 方法的操作。
HttpPutAttribute
作用域:All
说明:标识支持 HTTP PUT 方法的操作。
HttpDeleteAttribute
作用域:All
说明:标识支持 HTTP DELETE 方法的操作。
FromBodyAttribute
作用域:Property,Parameter
说明:指定应使用请求正文绑定参数或属性。
FromFormAttribute
作用域:Property,Parameter
说明:指定应在请求正文中使用表单数据绑定参数或属性。
FromHeaderAttribute
作用域:Property,Parameter
说明:指定应使用请求标头绑定参数或属性。
FromQueryAttribute
作用域:Property,Parameter
说明:指定应使用请求查询字符串来绑定参数或属性。
FromRouteAttribute
作用域:Property,Parameter
说明:指定应使用当前请求中的路由数据来绑定参数或属性。
FromServicesAttribute
作用域:Parameter
说明:指定应该使用请求服务绑定操作参数。
ActionContextAttribute
作用域:Property
说明:指定在创建控制器时应使用当前设置控制器属性 ActionContext 。 该属性必须具有公共集方法。
ActionNameAttribute
作用域:Method
说明:指定操作的名称。
AreaAttribute
作用域:Class ,Method
说明:指定包含控制器或操作的区域。
ControllerAttribute
作用域:Class
说明:指示将此特性应用于的类型和任何派生类型被默认控制器发现机制视为控制器,除非 NonControllerAttribute 应用于层次结构中的任何类型。
ControllerContextAttribute
作用域:Property
说明:指定在创建控制器时应使用当前设置控制器属性 ControllerContext 。 该属性必须具有公共集方法。
FormatFilterAttribute
作用域:Class,Method
说明:一个筛选器,它将使用路由数据或查询字符串中的格式值对从操作返回的 ObjectResult 设置内容类型。
我们还是用.NET 的web项目做示范,写一个用特性来捕获异常的方法。首先定义一个特性类。继承自Attribute
和IExceptionFilter
。
CatchExceptionAttribute.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Nlog_demo
{
public class CatchExceptionAttribute : Attribute, IExceptionFilter
{
public CatchExceptionAttribute()
{
}
///
/// 发生异常进入
///
///
public async void OnException(ExceptionContext context)
{
ContentResult result = new ContentResult
{
StatusCode = 500,
ContentType = "text/json;charset=utf-8;"
};
result.Content = "啊哦,出现异常了。";
context.Result = result;
context.ExceptionHandled = true;
}
}
}
接着在statup中注册一下。
builder.Services.AddScoped<CatchExceptionAttribute>();
然后在方法中就可以使用了,在方法上面加上特性名就可以了。下面的代码string转int肯定会报错的。
[CatchException]
public IActionResult Index()
{
var a = "hello world";
var b = Convert.ToInt32(a);
return View();
}
项目报错,同时控制台也打印了一个输出。如果不想页面出现这样的提示的话,可以把
OnException
方法修改如下。
public async void OnException(ExceptionContext context)
{
ContentResult result = new ContentResult
{
StatusCode = 500,
ContentType = "text/json;charset=utf-8;"
};
result.Content = "啊哦,出现异常了。";
context.Result = result;
context.ExceptionHandled = true;
}
这次页面提示就是处理后的效果了。
Study hard and make progress every day.