特性随笔
MSDN是这样描述的:特性提供功能强大的方法,用以将声明信息与代码(类型、方法、属性等)相关联。属性与程序实体关联后,即可在运行时使用名为“反射”的技术查询属性。
简单的理解,它是程序集,类,方法,属性等的附加信息。
基础概念以及用法,参见msdn
1.特性参数
特性本身就是一个类,直接或间接继承自System.Attribute,它也具有属性,字段,方法,构造函数等。
特性参数,包括定位参数、未命名参数或命名参数。定位参数总出现第一个,实际上就是特性构造函数的参数;命名参数为特性的属性。
2.AttributeUsage的继承
在自定义特性中,命名参数Inherited=true,该命名参数指定所指示的特性能否由派生类和重写成员继承。
/// <summary>
/// 自定义特性(使用在方法和属性上,允许多次使用,默认inherited为true)
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true,Inherited=true)]
public class Author : System.Attribute
{
public string AuthorName { get; set; }
public string Version { get; set; }
public Author()
: this(null, null)
{
}
public Author(string authorName, string version)
{
this.AuthorName = authorName;
this.Version = version;
}
}
使用特性
public class Sample_01
{
[Author()]
public virtual void Method() { }
[Author()]
public virtual string Property { get; set; }
}
public class BaseClass1 : Sample_01
{
}
public class BaseClass2 : Sample_01
{
public override void Method() { }
public override string Property { get; set; }
}
使用反射观察,派生类继承基类的特性。
public static void Run()
{
int a, b;
BaseClass1 s1 = new BaseClass1();
a = s1.GetType().GetMethod("Method").GetCustomAttributes(true).Length;
b = s1.GetType().GetProperty("Property").GetCustomAttributes(true).Length;
Console.WriteLine("1.inherited");
Console.WriteLine("Method GetCustomAttributes Length:{0}", a); //1
Console.WriteLine("Property GetCustomAttributes Length:{0}", b); //1
}
而在派生类重写基类的成员时,属性和事件的特性不被继承
public static void Run()
{
BaseClass2 s2 = new BaseClass2();
Console.WriteLine("2.override");
a = s2.GetType().GetMethod("Method").GetCustomAttributes(true).Length;
b = s2.GetType().GetProperty("Property").GetCustomAttributes(true).Length;
Console.WriteLine("Method GetCustomAttributes Length:{0}", a); //1
Console.WriteLine("Property GetCustomAttributes Length:{0}", b); //0
}
网上解释是这样的,CLS无法搜索到覆盖的属性或事件上所继承的特性
解决方法如下,派生类下重新的属性不仅继承基类的特性,还有它自己的特性
public class BaseClass
{
public virtual int property
{
[Attribute1,Attribute2, ... Attribute100]
get{...}
}
}
public class MyClass : BaseClass
{
public override int property
{
[Attribute101]
get{...}
}
}
3.利用反射获取特性信息
//自定义特性
[AttributeUsage(AttributeTargets.Class)]
class TableAttribute : Attribute
{
public TableAttribute() { }
public TableAttribute(string name) { Name = name; }
public string Name { get; set; }
}
[AttributeUsage(AttributeTargets.Property)]
class ColumnsAttribute : Attribute
{
public string ColumnName { get; set; }
public int Length { get; set; }
public DataType ColumnType { get; set; }
public ColumnsAttribute(string columnName, int length, DataType columnType)
{
ColumnName = columnName;
Length = length;
ColumnType = columnType;
}
public ColumnsAttribute(string columnName, int length)
: this(columnName, length, DataType.Unknow)
{
}
public ColumnsAttribute(string columnName)
: this(columnName, 0, DataType.Unknow)
{
}
}
//实体类
[Table("Student"),Serializable]
public class Student
{
[Columns("StudentID", 20, DataType.Number)]
public int StudentID
{ get; set; }
[Columns("UserName", 10, DataType.Nvarchar2)]
public string Name
{ get; set; }
}
public static void Run()
{
Type t = typeof(Student);
//类特性
object[] attributes=t.GetCustomAttributes(typeof(TableAttribute),true);
foreach (var attribute in attributes)
{
TableAttribute attr = attribute as TableAttribute;
Console.WriteLine("表名:" + attr.Name);
}
System.Reflection.PropertyInfo[] properties = t.GetProperties();
foreach (var property in properties)
{
Console.WriteLine("属性名:" + property.Name);
object[] arrays2 = property.GetCustomAttributes(typeof(ColumnsAttribute), true);
foreach (var a in arrays2)
{
Console.WriteLine("\t特性:" + ((ColumnsAttribute)a).ColumnName);
}
}
}

浙公网安备 33010602011771号