使用Attribute的时候大多需要用到反射,所以放在一起。
Attribute:
我的理解是,它可以给你的类、方法、字段等添加一些描述性语言,在运行期间又可以通过反射的方法获取它的内容。
在编译期间就初始化好了。
反射:
通过反射可以在不了解对象的内容时,操作对象。
优点:在运行的时候才需要获取对象内容,提示程序的灵活性,降低耦合等。
缺点:操作效率低,会暴露私有的属性和方法等。
举例:
我有一个父类Animal,他有四个子类:Cat、Dog、Lion、Tiger。
public class Animal
{ }
public class Cat : Animal
{ }
public class Dog : Animal
{ }
public class Lion : Animal
{ }
public class Tiger : Animal
{ }
假设我们需要写一个方法,描述动物叫声的大小,我们认为Cat和Dog的叫声小,属于一类,Lion和Tiger的叫声大,属于一类。
如果不用Attribute和反射机制,那么我们需要给每个动物都定义叫声这个方法。但是,如果用Attribute和反射机制用的话,则,我们可以把Cat和Dog定义一个方法,Lion和Tiger定义一个方法。
定义一个自定义attribute:
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CallBindingAttribute : Attribute
{
private Type m_CallType;
public Type CallType
{
get { return m_CallType; }
}
internal CallBindingAttribute(Type callType)
{
m_CallType = callType;
}
}
定义动物叫声:
public class CallType
{
public enum Level
{
LOW = 1,
HIGH = 2
}
private Level m_CallLevel;
public Level CallLevel
{
get { return m_CallLevel; }
internal set { m_CallLevel = value; }
}
}
定义大型动物和小动物叫声,并绑定我们自定义的属性:
[CallBinding(typeof(Cat))]
[CallBinding(typeof(Dog))]
public class SmallAnimalType : CallType
{
public SmallAnimalType()
{
this.CallLevel = Level.LOW;
}
}
[CallBinding(typeof(Lion))]
[CallBinding(typeof(Tiger))]
public class BigAnimalType : CallType
{
public BigAnimalType()
{
this.CallLevel = Level.HIGH;
}
}
通过反射获取合适动物叫声:
public static List<CallType> Calls = new List<CallType>();
public static List<CallType> GetFaultTypes(Type type)
{
List<CallType> cts = new List<CallType>();
foreach (CallType ct in Calls)
{
object[] os = ct.GetType().GetCustomAttributes(typeof(CallBindingAttribute), false); // 反射方法,通过绑定的CallBindingAttribute和类获取到合适的叫声
foreach (CallBindingAttribute dba in os)
{
if (dba.CallType == type || type.IsSubclassOf(dba.CallType))
{
cts.Add(ct);
break;
}
}
}
return cts;
}
根据动物类型获取到动物叫声:
SmallAnimalType sType = new SmallAnimalType(); // 加载动物叫声
Calls.Add(sType);
BigAnimalType bType = new BigAnimalType();
Calls.Add(bType);
Dog dog = new Dog();
List<CallType> DogCall = GetFaultTypes(dog.GetType()); // 根据动物类型Dog获取狗的叫声
foreach (CallType callType in DogCall)
{
Console.WriteLine(callType.CallLevel.ToString()); //输出为狮子的叫声 HIGH
}
List<CallType> LionCall = GetFaultTypes(lion.GetType());
foreach (CallType callType in LionCall)
{
Console.WriteLine(callType.CallLevel.ToString());//输出为狗的叫声 LOW
}