C#自定义Attribute略谈
自定义特性允许任何人扩展元数据格式,如果在现有元数据格式中,一个字段或者方法的某个方面无法获取,那么就可以用自定义特性来表示那个方面。可以通过反射或者元数据接口来读取自定义特性。自定义特性作为BLOB(二进制大对象块)存储在CLR元数据中。自定义特性的存在与否不影响CLR对类型的处理。相反,自定义特性处于一种休眠状态,等待程序用反射或者元数据接口读取它们。
用枚举控制文件的读写很方便,但是需要在枚举前面加上FlagsAttribute进行修饰。下面可以看个实例,说明下有无FlagsAttribute修饰对结果的影响。
[Flags]
public enum Fruit
{
peach = 0x01,
banana = 0x02,
orange = 0x04,
apple = 0x10
}
static void Main(string[] args)
{
Fruit f=Fruit.peach|Fruit.banana;
Console.WriteLine("It has FlagsAttribute: " + f.ToString());
//Console.WriteLine("It has not FlagsAttribute: " + f.ToString());
Console.ReadLine();
}
有无Flags的运行结果:
查看Enum类的源代码的ToString()方法如下,IsDefined方法判断是否存在FlagsAttribute特性而执行不同的分支。
下面模仿Enum类的tostring()方法,我也写了个demo,可以更深刻的感悟自定义特性,一定要记住自定义特性不改变CLR对类型的处理方式,只是我们通过反射或元数据接口读取自定义特性实例数据来人为的控制程序执行执行分支。
public class FruitCustomAttribute : System.Attribute
{
public string Name = string.Empty;
public string FruitName = string.Empty;
public FruitCustomAttribute(string name)
{
Name = name;
}
}
[FruitCustom("Feng", FruitName = "Peach")]
public class Fruit
{
public override string ToString()
{
if (this.GetType().IsDefined(typeof(FruitCustomAttribute), false))
{
Attribute attr = Attribute.GetCustomAttribute(this.GetType(), typeof(FruitCustomAttribute), false);
if (attr != null)
{
return string.Format("{0} likes to eat {1}.", ((FruitCustomAttribute)attr).Name,
((FruitCustomAttribute)attr).FruitName);
}
}
return base.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Fruit f = new Fruit();
Console.WriteLine(f.ToString());
Console.ReadLine();
}
}
执行结果: