疑难杂症----特性(Attribute)

1. 百度上的一个有关Attribute的问题

//自定义了一个Attribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
class IStudentAttribute : Attribute
{
public string Name { get; set; }
public int Age { get; set; }
}

//下面是调用
[IStudent(Name = "abc", Age = 20)]
public void F()
{
//请问,Name 和 Age的值能取到吗?我没看到有什么用啊?
}

  下面是一个网友的最佳答案

  假设你的F()方法是定义在下面这个类里面:

    public class MyClass
{
[IStudent(Name = "abc", Age = 20)]
public void F()
{
}
}

  那么可以这么去取值:

    Type type = typeof(MyClass);
MethodInfo methodInfo = type.GetMethod("F");
if (methodInfo.IsDefined(typeof(IStudentAttribute), false))
{
object[] attributes = methodInfo.GetCustomAttributes(typeof(IStudentAttribute), false);
IStudentAttribute studentAttr = (IStudentAttribute)attributes[0];
Console.WriteLine(studentAttr.Name + studentAttr.Age);
}

  实际上,Attribute可以有很多用处,比如说,你可以在某个方法上做标记看有没有权限调用,或者在某个属性上标记,看要如何校验。例如(实在习惯用var关键字了,下面的代码都用var了,还有Linq):
  假设我们有这么一个标记来说明操作的权限:

    /// <summary>
/// 声明权限的标记
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class PermissonAttribute : Attribute
{
public string Role { get; set; }

public PermissonAttribute(string role)
{
this.Role = role;
}

public PermissonAttribute()
{
}
}

  有一个操作类应用了该标记:

    /// <summary>
/// 文件操作类
/// </summary>
public class FileOperations
{
/// <summary>
/// 任何人都可以调用Read
/// </summary>
[Permisson("Anyone")]
public void Read()
{
}

/// <summary>
/// 只有文件所有者才能Write
/// </summary>
[Permisson("Owner")]
public void Write()
{
}
}

  然后我们写一个工具类来检查操作权限

    /// <summary>
/// 调用操作的工具类
/// </summary>
public static class OperationInvoker
{
public static void Invoke(object target, string role, string operationName, object[] parameters)
{
var targetType = target.GetType();
var methodInfo = targetType.GetMethod(operationName);

if (methodInfo.IsDefined(typeof(PermissonAttribute), false))
{
// 读取出所有权限相关的标记
var permissons = methodInfo
.GetCustomAttributes(typeof(PermissonAttribute), false)
.OfType<PermissonAttribute>();
// 如果其中有满足的权限
if (permissons.Any(p => p.Role == role))
{
methodInfo.Invoke(target, parameters);
}
else
{
throw new Exception(string.Format("角色{0}没有访问操作{1}的权限!", role, operationName));
}
}
}
}

  最后,在使用的时候:

var role = "Anyone";
var opertion = new FileOperations();
// 可以正常调用Read
OperationInvoker.Invoke(operation, "Read", null);
// 但是不能调用Write
OperationInvoker.Invoke(operation, "Write", null);

 

  经典案例:

using System;
using System.Reflection; //应用反射技术获得特性信息

namespace Anytao.net
{
//定制特性也可以应用在其他定制特性上,
//应用AttributeUsage,来控制如何应用新定义的特性
[AttributeUsageAttribute(AttributeTargets.All, //可应用任何元素
AllowMultiple = true, //允许应用多次
Inherited = false)] //不继承到派生类
//特性也是一个类,
//必须继承自System.Attribute类,
//命名规范为:"类名"+Attribute。
public class MyselfAttribute : System.Attribute
{
//定义字段
private string _name;
private int _age;
private string _memo;

//必须定义其构造函数,如果不定义有编译器提供无参默认构造函数
public MyselfAttribute()
{
}
public MyselfAttribute(string name, int age)
{
_name = name;
_age = age;
}

//定义属性
//显然特性和属性不是一回事儿
public string Name
{
get { return _name == null ? string.Empty : _name; }
}

public int Age
{
get { return _age; }
}

public string Memo
{
get { return _memo; }
set { _memo = value; }
}

//定义方法
public void ShowName()
{
Console.WriteLine("Hello, {0}", _name == null ? "world." : _name);
}
}

//应用自定义特性
//可以以Myself或者MyselfAttribute作为特性名
//可以给属性Memo赋值
[Myself("Emma", 25, Memo = "Emma is my good girl.")]
public class Mytest
{
public void SayHello()
{
Console.WriteLine("Hello, my.net world.");
}
}

public class Myrun
{
public static void Main(string[] args)
{
//如何以反射确定特性信息
Type tp = typeof(Mytest);
MemberInfo info = tp;
MyselfAttribute myAttribute =
(MyselfAttribute)Attribute.GetCustomAttribute(info, typeof(MyselfAttribute));
if (myAttribute != null)
{
//嘿嘿,在运行时查看注释内容,是不是很爽
Console.WriteLine("Name: {0}", myAttribute.Name);
Console.WriteLine("Age: {0}", myAttribute.Age);
Console.WriteLine("Memo of {0} is {1}", myAttribute.Name, myAttribute.Memo);
myAttribute.ShowName();
}

//多点反射
object obj = Activator.CreateInstance(typeof(Mytest));

MethodInfo mi = tp.GetMethod("SayHello");
mi.Invoke(obj, null);
Console.ReadLine();
}
}
}

2. 下面是一个新浪网友的理解

  Attribute. 对一个类型class的描述, 就像public等访问修饰符,或者方法method,属性property等类似。意义在于添加在指定类型的描述,从而通过定制来使用该attribute类型里面的成员(属性或者方法)。.net通过反射来获取注册到指定类型或者成员的所有attribute,并按照framework里制定好的规则去使用或者执行该attribute类实例。可被继承.
using System;
using System.Reflection;

namespace CustomAttrCS {
// An enumeration of animals. Start at 1 (0 = uninitialized).
public enum Animal {
// Pets.
• Dog = 1,
• Cat,
• Bird,
• }

// A custom attribute to allow a target to have a pet.
public class AnimalTypeAttribute : Attribute {
// The constructor is called when the attribute is set.
public AnimalTypeAttribute(Animal pet) {
• thePet = pet;
• }

// Keep a variable internally ...
protected Animal thePet;

// .. and show a copy to the outside world.
public Animal Pet {
get { return thePet; }
set { thePet = Pet; }
• }
• }

// A test class where each method has its own pet.
class AnimalTypeTestClass {
• [AnimalType(Animal.Dog)]
public void DogMethod() {}

• [AnimalType(Animal.Cat)]
public void CatMethod() {}

• [AnimalType(Animal.Bird)]
public void BirdMethod() {}
• }

class DemoClass {
static void Main(string[] args) {
• AnimalTypeTestClass testClass = new AnimalTypeTestClass();
• Type type = testClass.GetType();
// Iterate through all the methods of the class.
foreach(MethodInfo mInfo in type.GetMethods()) {
// Iterate through all the Attributes for each method.
foreach (Attribute attr in
• Attribute.GetCustomAttributes(mInfo)) {
// Check for the AnimalType attribute.
if (attr.GetType() == typeof(AnimalTypeAttribute))
• Console.WriteLine(
"Method {0} has a pet {1} attribute.",
• mInfo.Name, ((AnimalTypeAttribute)attr).Pet);
• }

• }
• }
• }
• }







 

 

 

 

 

 

 

 

 

 

 

 

posted on 2011-10-18 13:05  啊風  阅读(350)  评论(0编辑  收藏  举报