Skip to content

.NET Core 实战 [No.94~98] 特性

🏷️ 《.NET Core 实战》

特性是一种比较特殊的类,通常作为代码对象的附加部分,用于向 CLR 提供一些补充信息。

特性在项目中应用很广,比如 Web 服务(ASMX) 中一般都会用到如下特性:

csharp
[WebMethod(Description = "", EnableSession = false)]
[ScriptMethod(UseHttpGet = false)]

再比如 MVC 项目中的路由、权限、验证等:

csharp
[Route("blog/{id=}")]

[AllowAnonymous]

[Required]

特性具有以下特征:

  1. Attribute 类派生
  2. 类名一般以 Attribute 结尾。这是一个约定,建议开发者遵守这一约定。
  3. 必须在自定义的特性类上应用 AttributeUsageAttribute
csharp
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method, AllowMultiple  = true)]
class DemoAttribute : Attribute
{
    public string Description { get; set; }
}

AttributeUsage 默认的构造函数有一个枚举参数 validOn,可以指定特性的应用目标,支持枚举的组合。
另外 AttributeUsage 特性还有一个属性 AllowMultiple,默认值为 false,表示是否支持在同一个对象上应用复数个特性的实例。

特性本质上是一个类,也有构造函数。当使用无参构造函数时,可以省略 ()

csharp
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method, AllowMultiple  = true)]
class DemoAttribute : Attribute
{
    public DemoAttribute()
    {
    }

    public DemoAttribute(string description)
    {
        Description = description;
    }

    public string Description { get; set; }
}

可以通过 GetCustomAttribute<T>() 方法获取对应属性、方法等上面应用的特性。
这些扩展方法位于 System.Reflection.CustomAttributeExtensions 类中。

Test.cs

csharp
class Test
{
    [Demo("姓名")]
    public string Name { get; set; }
}
csharp
var type = typeof(Test);
var prop = type.GetProperty("Name", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
if (prop == null) return;
var att = prop.GetCustomAttribute<DemoAttribute>();
Console.WriteLine($"The description of Test.Name is \"{att.Description}\" .");
// The description of Test.Name is "姓名" .

方法的参数上也是可以应用特性的,如:

csharp
public void AddBlog([FromBody] BlogInfo blogInfo) {
    // do something
}

另外,特性也可以应用于方法的返回值,这需要在特性定义的 AttributeUsage 上添加 AttributeTargets.ReturnValue 目标。

csharp
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.ReturnValue, AllowMultiple  = true)]
class DemoAttribute : Attribute
{
    // ...
}
csharp
[return: Demo]
static string SaySomething() => "Hello";

参考:《.NET Core 实战:手把手教你掌握 380 个精彩案例》 -- 周家安 著