特性
引
先看一个例子:
在VS中添加一个类库项目和一个控制台项目,在控制台项目中编写以下代码。(控制台项目添加类库项目的程序集)
static void Main(string[] args)
{
Assembly assembly = Assembly.GetAssembly(typeof(Class1));
Console.WriteLine("程序集名称:"+assembly.FullName);
assembly.GetCustomAttributes();
Console.WriteLine("程序集Title:" +
assembly.GetCustomAttribute<AssemblyTitleAttribute>().Title);
Console.WriteLine("程序集描述:" +
assembly.GetCustomAttribute<AssemblyDescriptionAttribute>().Description);
Console.WriteLine("程序集公司:" +
assembly.GetCustomAttribute<AssemblyCompanyAttribute>().Company);
Console.Read();
}
其中Class1是类库项目的类。
执行后可以得到该类库项目输出的程序集的信息。例如:
在VS创建类库项目(以及其他的一些项目)时,会添加一个名为“AssemblyInfo.cs”的文件,其中内容如下:
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("ClassLibrary1")]
[assembly: AssemblyDescription("测试程序集")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("程序开发公司")]
[assembly: AssemblyProduct("ClassLibrary1")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("e15c7334-bcfc-4c09-a0bc-3798f7742fc8")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
这个文件并不是某个类文件,而是为程序集添加额外说明信息的文件,其中运用了很多特性——即使用"[]"包括起来的内容。
特性
特性可以可以为程序添加更多的元数据信息。上面的例子中,使用程序集特性为程序集class1添加了标题,程序集描述,创建公司,版权声明等等信息。除此之外,特性还可以用于如:
- 类
- 委托
- 枚举
- 事件
- 字段
- 泛型参数
- 接口
- 方法
- 属性
····
(可以参考AttributeTargets提供的选项)
特性可以作为一种特殊的类来对待,只是特性类统一继承于System.Attribute,使用特性时,通常可以不带Attribute后缀。
一个自定义特性的例子
一个普通的类继承System.Attribute之后,就成为了一个特性类。在命名类名通常会加上Attribute,例如:
[System.AttributeUsage(AttributeTargets.Property, Inherited = false,
AllowMultiple = true)]
sealed class RequiredAttribute : Attribute
{
private bool flag;
public RequiredAttribute(bool flag)
{
this.flag = flag;
}
public bool Flag
{
get { return flag; }
}
}
上面的特性Required标记了某个属性是必须的,并且通过AttributeTargets确定了只能用于属性字段。
可以看到:
特性类是密封类;
特性类也有构造器;
其中System.AttributeUsage可以用来限定自定义特性,(相当于特性的特性)
使用特性修饰
如下代码,定义了一个类,并限定某些字段为必须的
public class FormClass
{
[Required(true)]
public string ID { get; set; }
[Required(true)]
public string Name { get; set; }
public string Birthday { get; set; }
}
在网页提交表单是通常要做一些验证,常常就有检验字段是否为空的(当然,表单验证通常不会放在后台来做)。对于FormClass,验证其是否符合要求,可以用反射的方法获取所有的属性,获取属性上的特性标记,判断是否符合特性的要求。
public class Validator<T>
{
private T data;
public Validator(T data){
this.data = data;
}
//是否已经验证
bool isValidate { get; set; }
//验证方法
bool Validate()
{
PropertyInfo[] properties = data.GetType().GetProperties();
foreach (var item in properties)
{
RequiredAttribute required =
item.GetCustomAttribute<RequiredAttribute>();
if (required!= null&&required.Flag == true && item.GetValue(data) ==
null)
{
return false;
}
else
{
continue;
}
}
return true;
}
}