(16)反射、特性和动态编程

来源:互联网 发布:24周大排畸数据看男女 编辑:程序博客网 时间:2024/06/05 07:10
 

**反射:是在在一个程序集中的元数据进行检查的过程。除此之外,可以利用反射枚举程序集中的所有类型,并搜索满足特定条件的那些类型。通过System.type的实例来访问一个类型的元数据。

利用反射,可以访问程序集中的元数据,使用元数据,在运行时动态调用一个类型的成员,而不是在执行编译时绑定。

**使用

System.Type访问元数据。

Type.Name

Type.IsPublic

Type.BaseType

Type.GetInterfaces()

Type.Assembly:类型是在哪个程序集中定义的。

Type.GetProperties()

Type.GetMethod()

Type.GetFileds()

Type.GetCustomAttributes():都有什么特性在修饰一个类型....

**GetType():object的方法

使用GetType()的关键是活的对象实例。静态类是无法实例化的,所以没有办法调用GetType()

            DateTime datetime = new DateTime();            Type type = datetime.GetType();             foreach(System.Reflection.PropertyInfo property in type.GetProperties())            {                Console.WriteLine(property.Name);            }       /*  Date           Day           DayOfWeek           DayOfYear           Hour           Kind           Millisecond           Minute           Month           Now           UtcNow           Second           Ticks           TimeOfDay           Today           Year        */

*typeof()方法在编译时绑定到一个特定的Type实例。

            //使用typeof()创建一个System.Type()实例             ThreadPriorityLevel priority;             priority = (ThreadPriorityLevel)Enum.Parse(typeof(ThreadPriorityLevel),"Idle");

**动态成员调用【还不是很理解,先放着疑问

                    PropertyInfo property =                        commandLine.GetType().GetProperty(option, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);                    if (property != null)                    {                        if (property.PropertyType == typeof(bool))                        {                            //last parameters for handong indexers                            property.SetValue(commandLine,true,null);                            success = true;                        }                        else if(property.PropertyType==typeof(string))                        {                            property.SetValue(commandLine,optionParts[1],null);                            success = true;                        }                        else if (property.GetType().IsEnum)                        {                            try                            {                                property.SetValue(commandLine, Enum.Parse(typeof(ProcessPriorityClass), optionParts[1], true), null);                            }

**泛型上的反射

在泛型类型上执行运行时反射,将判断出一个类或方法是否包含泛型类型,并确定它包含的任何类型参数。

1.判断类型参数的类型,获得Type 的对象实例后,就可以在类型参数上执行反射,从而判断它的行为,并针对具体类型来调整方法,使其更有效的支持这种方法。

public class stack<T>

{

...

public void Add(T t)

{

Type t= typeof(T);

}

}
2.判断类或方法是否支持泛型

            Type type;            type=typeof(System.Nullable<>);            //type.ContainsGenericParameters:判断类或方法是否包含未设置的参数。            Console.WriteLine(type.ContainsGenericParameters);            Console.WriteLine(type.IsGenericType);            type=typeof(System.Nullable<DateTime>);            Console.WriteLine(!type.ContainsGenericParameters);            //判断当前类型是否是泛型类型。            Console.WriteLine(type.IsGenericType);           /* True            True            True            True*/

3.为泛型类或方法获取类型参数:可以调用GetGenericArguments()方法,从一个泛型类型获取泛型实参或(类型参数)的一个类表。这样得到的是一个System.Type实例构成的一个数组,其顺序与泛型类参数顺序一致。

            Dictionary<int,string> d=new Dictionary<int,string>();            Type t = d.GetType();            foreach (Type type in t.GetGenericArguments())            {                System.Console.WriteLine("Type parameter:" +type.FullName);            }            //Type parameter:System.Int32            //Type parameter:System.String

**特性(Attribute):利用特性,我们可以指定与被修饰的构造有关的额外元数据。使用特性,可以将一个属性修饰为Required(必要)的,并提供一个/?选项别名。换言之,特性是将数据额外关联到一个属性(以及其他构造的)一种方式。

特性要放到他们修饰的那个构造之前的一对方括号中。

特性不适用于返回值、程序集和模块。
//可以用多个特型来修饰属性,用多个分开的[ ]或者一个[ , ]来修饰。

    private class CommandLineInfo    {        [CommandLineSwitchAlias("?")]        [CommandLineSwitchRequired]        public bool Help { get; set; }        [CommandLineSwitchAlias("FileName"),        CommandLineSwitchRequired]        public string Out { get; set; }        public ProcessPriorityClass Priority        {            get { return _Priority; }            set { _Priority = value; }        }        private ProcessPriorityClass _Priority = ProcessPriorityClass.Normal;    }

*程序集特性用于添加有关程序集的额外元数据。

例如:

// 有关程序集的常规信息通过以下// 特性集控制。更改这些特性值可修改// 与程序集关联的信息。[assembly: AssemblyTitle("Ex16_04")][assembly: AssemblyDescription("")][assembly: AssemblyConfiguration("")][assembly: AssemblyCompany("")][assembly: AssemblyProduct("Ex16_04")][assembly: AssemblyCopyright("Copyright ©  2011")][assembly: AssemblyTrademark("")][assembly: AssemblyCulture("")]

*制定一个return 特性:[return:],除此之外,还有module: class: method:等目标。其中class:和method:是可选的。

**自定义特性:定义一个类,从System.Attribute派生之后,一个普通的类就成为了一个特性。

public class CommandLineSwitchRequiredAttribute:Attribute

{

}

*获取一个自定义特性

        public static string[] GetMissingRequiredOptions(object commandLine)        {            StringCollection missingOptions = new StringCollection();            //利用反射来获取实例            PropertyInfo[] properties = commandLine.GetType().GetProperties();            foreach (PropertyInfo property in properties)            {                //用GetCustomAttributes()指定要查找的特性,并指定是否检查任何重载的方法。另外,也可以使用GetCustomAttributes()方法而不指定特性类型。                Attribute[] attributes = (Attribute[])property.GetCustomAttributes(typeof(commandLineInfoAttribute), false);                if ((attributes.Length > 0) && (property.GetValue(commandLine, null) == null))                {                    if (property.GetValue(commandLine, null) == null)                    {                        missingOptions.Add(property.Name);                    }                }             //...            }           //...;        } 

学习MSDN上的例子比较清楚

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.        //构造器的参数只有字面值和类型(typeof(int))        //        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);                }            }            //特性作用在属性上            //PropertyInfo property = typeof(className).GetProperties("help");            //classNameAttribute attribute=(classNameAttribute)property.GetCustomAttributes(typeof(classNameAttribute),false);            //...            Console.ReadKey();        }    }}

**疑问特性的其他知识,不是很理解P511-P526【留着研究下:】


           

 **使用动态对象编程

使用动态对象编程,开发人员可以用一个动态调用机制对摄像的操作进行编码。“运行时”会对程序执行时对这个机制进行解析,而不是有编译器在编译时验证和绑定。

在C# 4.0 中,提供了如下4个绑定方法

1.针对一个底层CLR类型使用反射。

2.调用一个自定义IDynamicMetaObjectProvider,它使一个DynamicMetaObject变得可用。

3.通过COM的IUnknow和IDispatch接口来调用。

4.调用由动态语言定义的类型。

             //对Dynamic使用GetType(),会返回基础类型,而不是Dynamic.            dynamic data = "Hello!  My name is Inigo Montoya";            Console.WriteLine(data.GetType());            Console.WriteLine(data);            //data.length 是动态表达式,将在运行时解析            //成功将引用类型转换成值类型。            //所有类型都能成功转换成dynamic对象。存在从任何引用类型到Dynamic的隐式转换。            //从dynamic到一个替代类型的成功转型需要依赖于基础类型。            data = (double)data.Length;            //任何Dynamic成员的调用返回的都是一个dynamic对象。            //但是下面打印的语句是一个基础类型,因为是对象已经经过编译好了。            data = data * 3.5 + 28.6;            Console.WriteLine(data.GetType());            if (data == 2.4 + 112 + 26.2)            {                Console.WriteLine("{0} makes for a long triathlon.", data);            }            else            {                data.NomExistentMethodCallStillCompiles();            }            //System.String            //Hello!  My name is Inigo Montoya            //System.Double            //140.6 makes for a long triathlon.

dynamic 是一个objec类型。
 **实现自定义动态对象:关键是实现System.Dynamic.IDynamicMetaObjectProvider接口。但是,不必从头实现接口,只要从System.Dynamic.DynamicObject派生出自定义的派生类型。你只要从众多的成员中重写不合适的。

    public class DynamicXml : DynamicObject    {        private XElement Element { get; set; }        public DynamicXml(XElement element)        {            Element = element;        }        public static DynamicXml Parse(string text)        {            return new DynamicXml(XElement.Parse(text));        }        //动态取值        public override bool TryGetMember(GetMemberBinder binder, out object result)        {            bool success = false;            result = null;            //FirstOrDefault():返回序列中的第一个元素,如果不包含任何元素,则返回默认值。            //Descendants():按文档顺序返回此文档或元素的经过筛选的子代元素集合            XElement firstDescendant = Element.Descendants(binder.Name).FirstOrDefault();            if(firstDescendant!=null)            {                if(firstDescendant.Descendants().Count()>0)                {                    result = new DynamicXml(firstDescendant);                }                else                 {                    result=firstDescendant.Value;                }                success =true;            }            return success;        }        //动态赋值        public override bool TrySetMember(SetMemberBinder binder,object value)        {            bool success=false;            XElement firstDescendant=Element.Descendants(binder.Name).FirstOrDefault();            if (firstDescendant != null)            {                if(value.GetType()==typeof(XElement))                {                    firstDescendant.ReplaceWith(value);                }                else                {                  firstDescendant.Value=value.ToString();                }                success=true ;            }             return success;        }       }


原创粉丝点击