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);
    • }

    • }
    • }
    • }
    • }







  • 相关阅读:
    打造基于CentOS7的xfce最简工作环境
    Linux下C程序的编辑,编译和运行以及调试
    修正 XE6 TListView 上方 SearchBok 右边的清除钮显示
    TabControl 显示彩色的图示 (XE6 Firemonkey)
    TSwitch 中文简繁显示支持(XE6 Android)
    改变 TMemo 的背景颜色 (Firemonkey)
    修正 XE5 Android 键盘三个问题
    Delphi 收藏
    展示 Popup 的使用方法
    ListView 下拉更新 (支持 Android)
  • 原文地址:https://www.cnblogs.com/johnsmith/p/2216366.html
Copyright © 2011-2022 走看看