zoukankan      html  css  js  c++  java
  • 疑难杂症特性(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);
    • }

    • }
    • }
    • }
    • }







  • 相关阅读:
    调试WEB APP多设备浏览器
    Android病毒家族及行为(一)
    如何判断Android设备是否为模拟器
    python操作MongoDB
    python面试题大全(二)
    白话经典算法系列之——快速排序
    白话经典算法系列之——希尔排序的实现
    白话经典算法系列之——直接插入排序的三种实现
    白话经典算法系列之——冒泡排序的三种实现(转)
    MySQL 数据库赋予用户权限操作表
  • 原文地址:https://www.cnblogs.com/johnsmith/p/2216366.html
Copyright © 2011-2022 走看看