zoukankan      html  css  js  c++  java
  • CLR via C# 笔记 -- 特性(18)

    1. 特性继承自System.Attribute,能作用于TypeDef(类、结构、枚举、接口和委托),MethodDef(含构造器),ParamDef,FieldDef,PropertyDef,EventDef,AssemblyDef,ModuleDef。

    2. AttributeUsageAttribute 设置特性作用范围,AllowkMultiple = true 允许多次设置,Inherited = true 同时应用于派生类和重写方法。

    3. 应将特性想像成逻辑状态容器。应该只提供一个公共构造器来接受特性的强制性(定位性)状态信息。

    4. 当编译器检测到向目标元素应用了定制特性时,会调用特性类的构造器,向它传递任何指定的参数,从而构造特性类的实例。然后,编译器采用增强型构造器语法所指定的值,对任何公共字段和属性进行初始化。构造并初始化好定制特性类的对象后,编译器将它的状态序列化到目标元素的元数据表记录中。为方便理解,可以这样想象定制特性:它是类的实例,被序列化成驻留在元数据中的字节流。运行时可对元数据中的字节进行反序列化,从而构造出类的实例。实际发生的事情是:编译器在元数据中生成创建特性类的实例所需的信息。每个构造器参数都是1字节的类型ID,后跟具体的值。对构造器的参数进行序列化时,编译器先写入字段/属性名称,再跟上1字节的类型ID,最后是具体的值。如果是数组,则会先保存数组元素的个数,再跟上每个单独的元素。

    5. Type 的 IsDefined方法要求系统查看枚举类型的元数据。

    6. 通过 System.Reflection.CustomAttributeExtensions.GetCustomAttributes()方法获取特性

    [Serializable]
    [DefaultMember("Main")]
    [DebuggerDisplay("Richter", Name = "Jeff", Target = typeof(Program))]
    public class Program
    {
        [Conditional("Debug")]
        [Conditional("Release")]
        public void DoSomeThing() { }
    
        [CLSCompliant(true)]
        [STAThread]
        public static void Main() 
        {
            ShowAttributes(typeof(Program));
    
            var members = from m in typeof(Program).GetTypeInfo().DeclaredMembers.OfType<MethodBase>()
                            where m.IsPublic
                            select m;
    
            foreach (var member in members)
            {
                ShowAttributes(member);
            }
    
        }
    
        private static void ShowAttributes(MemberInfo attributeTarget) 
        {
            var attributes = attributeTarget.GetCustomAttributes<Attribute>();
            Console.WriteLine("Attributes applied to {0}:{1}", attributeTarget.Name, (attributes.Count() == 0 ? "None" : string.Empty));
            foreach (Attribute attribute in attributes) 
            {
                Console.WriteLine(" {0}", attribute.GetType().ToString());
                if (attribute is DefaultMemberAttribute) 
                {
                    Console.WriteLine(" MemberName={0}", ((DefaultMemberAttribute)attribute).MemberName);
                }
                if (attribute is ConditionalAttribute) 
                {
                    Console.WriteLine(" ConditionString={0}", ((ConditionalAttribute)attribute).ConditionString);
                }
                if (attribute is CLSCompliantAttribute)
                {
                    Console.WriteLine(" IsCompliant={0}", ((CLSCompliantAttribute)attribute).IsCompliant);
                }
    
                DebuggerDisplayAttribute dda = attribute as DebuggerDisplayAttribute;
                if(dda != null)
                {
                    Console.WriteLine(" Value={0}, Name={1}, Target={2}", dda.Value, dda.Name, dda.Target);
                }
            }
            Console.WriteLine();
        }
    }

    7. 特性实例相互匹配,用 Equip 或 Match

    [Flags]
    internal enum Accounts
    {
        Savings = 0x0001,
        Checking = 0x0002,
        Brokerage = 0x0004
    }
    
    [AttributeUsage(AttributeTargets.Class)]
    internal sealed class AccountsAttribute : Attribute
    {
        private Accounts m_accounts;
        public AccountsAttribute(Accounts accounts)
        {
            m_accounts = accounts;
        }
        public override bool Match(object obj)
        {
            if (obj == null)
            {
                return false;
            }
            if (this.GetType() != obj.GetType())
            {
                return false;
            }
            AccountsAttribute other = (AccountsAttribute)obj;
    
            if ((other.m_accounts & m_accounts) != m_accounts)
            {
                return false;
            }
            return true;
        }
    
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }
            if (this.GetType() != obj.GetType())
            {
                return false;
            }
            AccountsAttribute other = (AccountsAttribute)obj;
            if (other.m_accounts != m_accounts)
            {
                return false;
            }
            return true;
        }
    
        public override int GetHashCode()
        {
            return (int)m_accounts;
        }
    }
    [Accounts(Accounts.Savings)]
    internal sealed class ChildAccount { }
    
    [Accounts(Accounts.Savings | Accounts.Checking | Accounts.Brokerage)]
    internal sealed class AdultAccount { }
    
    
    public sealed class Program
    {
        public static void Main()
        {
            CanWirteCheck(new ChildAccount());
            CanWirteCheck(new ChildAccount());
    
            CanWirteCheck(new Program());
        }
    
        private static void CanWirteCheck(object obj) 
        {
            Attribute checking = new AccountsAttribute(Accounts.Checking);
            Attribute validAccounts = Attribute.GetCustomAttribute(obj.GetType(), typeof(AccountsAttribute), false);
    
            if ((validAccounts != null) && checking.Match(validAccounts))
            {
                Console.WriteLine("{0} types can write checks.", obj.GetType());
            }
            else 
            {
                Console.WriteLine("{0} types can NOT write checks.", obj.GetType());
            }
        }
    }

    8. 查询CostomAttributeData对象,Constructor属性指出构造器方法将如何调用。ConstructorArguments属性以一个IList<CustomAttrbuteTypedArgument>实例的形式返回将传给这个构造器的实参。NamedArguments属性以一个IList<CustomAttributeNamedArgument>实例的形式,返回将设置的字段/属性

    private static void ShowAttributes(MemberInfo attributeTarget) 
    {
        var attributes = CustomAttributeData.GetCustomAttributes(attributeTarget);
        Console.WriteLine("Attributes applied to {0}: {1}", attributeTarget.Name, (attributes.Count == 0 ? "None" : string.Empty));
    
        foreach (var attribute in attributes)
        {
            // 显示所应用的每个特性的类型
            var t = attribute.Constructor.DeclaringType;
            Console.WriteLine(" {0}", t.ToString());
            Console.WriteLine("   Constructor called={0}", attribute.Constructor);
            var posArgs = attribute.ConstructorArguments;
            Console.WriteLine("   Positional arguments passed to constructor:{0}", (posArgs.Count == 0) ? "None" : string.Empty);
    
            foreach (var pa in posArgs) 
            {
                Console.WriteLine("   Type={0}, Value={1}", pa.ArgumentType, pa.Value);
            }
            var namedArgs = attribute.NamedArguments;
            Console.WriteLine("   Named arguments set after construction:" + ((namedArgs.Count == 0) ? "None" : string.Empty));
    
            foreach (var na in namedArgs) 
            {
                Console.WriteLine("   Name={0},Type={1},Value={2}", na.MemberInfo.Name, na.TypedValue.ArgumentType, na.TypedValue.Value);
            }
            Console.WriteLine();
        }
        Console.WriteLine();
    }
  • 相关阅读:
    Java在控制台运行IDE工具编写的程序
    mysql数据库执行存储过程问题
    Java之正则表达式在字符串中查找中文
    java之endwith()方法以及正则表达式匹配中文
    工具资源 Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore
    5、概率图模型 Inference-Variable_Elimination
    4、概率图模型:Template Modles
    3、概率图模型:Local Structure in Markov Network
    2、概率图模型: Markov Random Fields
    1、概率图模型: Bayesian Networks
  • 原文地址:https://www.cnblogs.com/Cxiaoao/p/14842472.html
Copyright © 2011-2022 走看看