(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; } }
- (16)反射、特性和动态编程
- 第十七章 反射、特性和动态编程
- 反射和特性(3.动态创建和调用)
- 反射和特性(1.反射基本信息)
- 反射和特性(2.反射特性信息)
- 定制特性和反射
- 24. 反射和特性
- C#反射和特性
- c# 反射和特性
- C# 特性和反射
- C#特性和反射
- 特性和反射
- LINQ、反射和特性
- 利用Objective-C的反射机制和运行时特性实现类静态方法的动态访问(一)
- 利用Objective-C的反射机制和运行时特性实现类静态方法的动态访问(二)
- C#自定义特性和反射
- C# Assembly反射和特性
- C#中的特性和反射
- 师兄帮帮忙:有困难,找师兄!
- web负载均衡小记
- Android - 系统应用源码开发入门
- phplist(及phpmailer)通过gmail发送邮件的配置方法
- HP大中华区总裁孙振耀退休感言
- (16)反射、特性和动态编程
- Your display is too small to run Menuconfig!
- DataGrid,DataList,Repeater等数据访问控件的区别及总结、使用Repeater控件显示数据
- 性能瓶颈分析方法
- java线程同步----生产消费
- Flex本地化开发——第二部分:在运行时加载资源
- yahoo邮件用phpmailer发送的示例
- New package not yet registered with the system 解决方法
- 比较详细的DataList控件的用法。(一)