none
C#中Attribute是怎么执行的 RRS feed

  • 问题

  • 各位好,

    我一直有个问题很迷惑,为什么一些类或者属性或方法等,用Attribute装饰后运行时会自动去“处理一些事情”?

    这个执行过程是怎样执行的,是否有一定的逻辑或者有一些执行顺序,望各位牛人帮忙,谢谢。


    Try your best, Work hard
    2010年4月14日 9:10

答案

  • 这个得两相情愿才行。

    加Attribute的时候得知道这个是有用的;用Attribute的时候得知道这个类有我预期的行为和功能。如果是把Attribute加到了毫无相关的类上,那就是毫无意义了。

    至于什么时候调用Attribute的属性,这个就看调用者了,比如控件,你拖到form上的时候ide就新建一个对象,然后读取上面的Attribute,比如 Browsable, DefaultValue 之类的,并添加到设计器的属性里面。

    又如 Serializable ,则是在你调用 Formatter.Serialize() 的时候检查对象的每一个公共字段和属性,如果有 NonSerialize 则跳过,否则就序列化进去了。

    总之都是在预期的行为里对Attribute进行检查的。如果你想知道系统某个操作做了些什么,那么reflector,反编译去找源代码一探究竟吧


    霸王
    2010年4月19日 10:22

全部回复

  • 关注。

    2010年4月14日 9:35
  • 很简单,看例子。
    当NewName被设置的时候,会调用函数进行对应的修改。

    Cleass ClassA
    {
        private string _Newname;
        public string NewName
       {
          get{this._Newname;}
          set
         {
             this._Newname = value;
             // 添加需要的函数调用。
          }
       }
    }

    2010年4月14日 10:15
  • 谢谢回复。

    我知道会调用函数处理。但是具体的执行流程是怎么回事还不清楚。

    比如自定义的attribute它怎么知道去执行某个方法去做些事情。


    Try your best, Work hard
    2010年4月14日 10:18
  •  

    牛人们帮忙看看吧。

    这个问题很难讲清楚还是我问的问题有问题。


    Try your best, Work hard
    2010年4月15日 5:44
  • 还是会在处理这个类的某个方法中通过反射判断类或者方法是否含有XxxAttribute,比如:

    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);
            }
    
          }
        }
      }
    }
    
    /*
     * Output:
     * Method DogMethod has a pet Dog attribute.
     * Method CatMethod has a pet Cat attribute.
     * Method BirdMethod has a pet Bird attribute.
     */
    

    2010年4月15日 6:11
  •  

    谢谢麒麟回复。

    这种方式我理解。但是还是没有解决我上面提到的问题。

    Attribute是怎么运行的,比如说SerializeAttribute是用来标识某个类是否可以被序列化,那为什么一旦标识上后,该类就可以被序列化了呢。

    这其中Attribute起到了什么作用。还有的特性被用来验证某个字段是否是满足要求,那这又是怎么运行的呢。

    所以归结到一点attribute到底是怎么运作的。

     


    Try your best, Work hard
    2010年4月15日 6:34
  •  

    请各位大侠能帮忙解释下啊。都休息一周末了。

    还是这个问题真的很难,或者是我的问题有问题啊。

     


    Try your best, Work hard
    2010年4月19日 7:54
  • Attribute 一般都是被动的,设置的时候很好理解,编译器把Attribute绑定到这个类的定义上,然后在用到的时候,每个用它的操作都会先去它的Attribute列表里找有没有自己想要的,如果有,则利用,没有则用默认。

    因此你也可以自己定义Attribute,设置后在用到这个类的时候用反射检查一遍Attribute里的内容,然后再决定如何操作。其实跟在类里面设置一个属性来进行判断没啥区别,只是Attribute可以通用而已(可以看成是Property的Interface,只读罢了)


    霸王
    2010年4月19日 9:17
  • 谢谢你的答复。

    但是我再麻烦你下,那它怎么知道哪个操作是它想要的呢。

    举个例子:

    你看我随便继承Attribute,里面有个Match方法,如果我重写这个方法,那执行的时候运行时怎么知道这个方法是想要的然后就执行它呢。


    Try your best, Work hard
    2010年4月19日 10:05
  • 这个得两相情愿才行。

    加Attribute的时候得知道这个是有用的;用Attribute的时候得知道这个类有我预期的行为和功能。如果是把Attribute加到了毫无相关的类上,那就是毫无意义了。

    至于什么时候调用Attribute的属性,这个就看调用者了,比如控件,你拖到form上的时候ide就新建一个对象,然后读取上面的Attribute,比如 Browsable, DefaultValue 之类的,并添加到设计器的属性里面。

    又如 Serializable ,则是在你调用 Formatter.Serialize() 的时候检查对象的每一个公共字段和属性,如果有 NonSerialize 则跳过,否则就序列化进去了。

    总之都是在预期的行为里对Attribute进行检查的。如果你想知道系统某个操作做了些什么,那么reflector,反编译去找源代码一探究竟吧


    霸王
    2010年4月19日 10:22
  • 补充一点:

    C# Attribute采用谁定义谁使用的原则。

    因此个人认为一般的系统自带的Attribute是受CLR支持的,因此有些调用执行等都有自己规定的流程。

    但是一些自定义的Attribute就得调用者自己在应用的时候去执行相应的方法。如ASP.NET MVC中定义的AuthorizationAttribute,这个在MVC后面的实现中都有自己的执行方式。


    Microsoft Online Community Support
    2010年4月20日 7:55
  • 继续关注中,我明白楼主的意思了,我现在也有同样的困惑,我自定义了一个 Attribute,里面也定义了一些操作,里面也有一些方法,当我给某个类加了 自定义的Attribute之后,编译器如何发现我这个类加了这个 Attribute之后而自动去执行我定义的那个方法
    2010年4月21日 12:36
  • 谢谢回复。

    我知道会调用函数处理。但是具体的执行流程是怎么回事还不清楚。

    比如自定义的attribute它怎么知道去执行某个方法去做些事情。


    Try your best, Work hard


    你好!

         实际上他不知道,需要你自己写反射的代码来利用这些标记的Attribute才可以,不然就只是简单的标记一下而已,不能做任何事情!


    周雪峰
    2010年4月24日 2:23
    版主