C#学习笔记12
2017-01-23 20:26
197 查看
1.在使用反射时,反射可以绕过安全访问级别(private、protected)修饰的类或属性,来获取需要的信息。
2.泛型的反射:可以使用Type.ContainsGenericParameters这个属性来判断一个类或方法是否包含尚未设置的泛型实参,Type.IsGenericType属性表示是否为泛型类型。
3.特性(Attribute):可以使用特性修饰类、接口。结构、枚举、委托、事件、属性、字段、方法、构造器、索引器、参数、类型参数、返回值、程序集、模块,使用特性的语法有2种,可为多个“[特性类型]”或“[特性类型,特性类型]”。对于其中列出多数构造来说,都可以使用上面的语法标记,但是这个语法不适合“返回值、程序集、模块”。
(1)程序集,[assembly:特性名]。
(2)模块,[module:特性名]。
(3)返回值,[return:特性名]。
4.大多数特性只针对特定的构造进行修饰,为了避免特性不恰当的使用,可以使用[AttributeUsageAttribute(AttributeTargets.xxx)]特性类进行标记特性限制。
5.具名参数:如[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]语法有别于构造器初始化语法,因为AttributeUsageAttribute类并不包含两个参数的构造器,虽然C#4.0支持命名参数,但也是指定方法本身所需的参数。具名参数是用于在特性构造器调用中设置特定的公共属性和字段,即使构造器不包含对应的参数,具名参数虽然是可选的,但它允许对特性的额外实例数据进行设置,同时无需提供一个对应的构造器参数。
6.序列化(Serializable):本质上System.Runtime,Serialization.SerializationInfo对象是由“名称/值”对构成的集合。在实现自定义的序列化时(需要实现ISerializable接口),内中会使用到SerializationInfo对象。
7.动态编程(Dynamic):反射的关键功能之一就是动态查找和调用特定类型的一个成员,这需要在执行时识别成员名或其他特征。在C#4.0中新增的动态编程-Dynamic,提供一个更简单的办法来通过反射调用成员,但这个技术的限制在于,编译时需要知道成员名和签名。若执行时发现事实上没有这个成员,调用就会引发一个RuntimeBinderException异常。可查看UseDynamic.Test()代码。
8.Dynamic:究其根本,Dynamic是一个Object,存在任何对象都能隐式转换成Dynamic,Dynamic可以显式转换成其他对象,所以Dynamic在行为上就像Object,类似于Object,它甚至为它的默认值返回null(default(dynamic))。dynamic特殊动态行为只在调用时才会出现,这个行为是它与Object区分开来的关键。任何dynamic的成员调用都会返回为dynamic类型,但若对Dynamic执行GetType(),会返回是编译好的类型(即最后赋值给动态变量的类型)。
9.实现自定义动态对象:定义自定义动态类型的关键是实现System.Dynamic.IDynamicMetaObjectProvider接口,但是不必从头实现,相反首先的方案是从System.Dynamic.DynamicObject类继承,并重写相应的方法。DynamicObject类已经实现了IDynamicMetaObjectProvider接口,提供了默认处理。可查看代码DynamicXml类,UseDynamic类中2个方法NormalMethod()与DynamicMethod()两者的比较。NormalMethod()方法使用一般的xml数据读取,DynamicMethod()方法使用了自定义动态对象解析xml内容。
View Code
-----------------以上内容根据《C#本质论 第三版》进行整理
2.泛型的反射:可以使用Type.ContainsGenericParameters这个属性来判断一个类或方法是否包含尚未设置的泛型实参,Type.IsGenericType属性表示是否为泛型类型。
3.特性(Attribute):可以使用特性修饰类、接口。结构、枚举、委托、事件、属性、字段、方法、构造器、索引器、参数、类型参数、返回值、程序集、模块,使用特性的语法有2种,可为多个“[特性类型]”或“[特性类型,特性类型]”。对于其中列出多数构造来说,都可以使用上面的语法标记,但是这个语法不适合“返回值、程序集、模块”。
(1)程序集,[assembly:特性名]。
(2)模块,[module:特性名]。
(3)返回值,[return:特性名]。
4.大多数特性只针对特定的构造进行修饰,为了避免特性不恰当的使用,可以使用[AttributeUsageAttribute(AttributeTargets.xxx)]特性类进行标记特性限制。
5.具名参数:如[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]语法有别于构造器初始化语法,因为AttributeUsageAttribute类并不包含两个参数的构造器,虽然C#4.0支持命名参数,但也是指定方法本身所需的参数。具名参数是用于在特性构造器调用中设置特定的公共属性和字段,即使构造器不包含对应的参数,具名参数虽然是可选的,但它允许对特性的额外实例数据进行设置,同时无需提供一个对应的构造器参数。
6.序列化(Serializable):本质上System.Runtime,Serialization.SerializationInfo对象是由“名称/值”对构成的集合。在实现自定义的序列化时(需要实现ISerializable接口),内中会使用到SerializationInfo对象。
7.动态编程(Dynamic):反射的关键功能之一就是动态查找和调用特定类型的一个成员,这需要在执行时识别成员名或其他特征。在C#4.0中新增的动态编程-Dynamic,提供一个更简单的办法来通过反射调用成员,但这个技术的限制在于,编译时需要知道成员名和签名。若执行时发现事实上没有这个成员,调用就会引发一个RuntimeBinderException异常。可查看UseDynamic.Test()代码。
8.Dynamic:究其根本,Dynamic是一个Object,存在任何对象都能隐式转换成Dynamic,Dynamic可以显式转换成其他对象,所以Dynamic在行为上就像Object,类似于Object,它甚至为它的默认值返回null(default(dynamic))。dynamic特殊动态行为只在调用时才会出现,这个行为是它与Object区分开来的关键。任何dynamic的成员调用都会返回为dynamic类型,但若对Dynamic执行GetType(),会返回是编译好的类型(即最后赋值给动态变量的类型)。
9.实现自定义动态对象:定义自定义动态类型的关键是实现System.Dynamic.IDynamicMetaObjectProvider接口,但是不必从头实现,相反首先的方案是从System.Dynamic.DynamicObject类继承,并重写相应的方法。DynamicObject类已经实现了IDynamicMetaObjectProvider接口,提供了默认处理。可查看代码DynamicXml类,UseDynamic类中2个方法NormalMethod()与DynamicMethod()两者的比较。NormalMethod()方法使用一般的xml数据读取,DynamicMethod()方法使用了自定义动态对象解析xml内容。
[Serializable] [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class MyDescriptionAttribute : Attribute { } public class UseDynamic { public static void Test() { dynamic data = "Hello! My name is Inigo Montoya"; Console.WriteLine(data); data = (double)data.Length; data = data * 3.5 + 28.6; if (data == 2.4 + 112 + 26.2) { Console.WriteLine("data for length : {0}", data); } else { data.NonExistentMethodCallStillCompiles(); } } public static void NormalMethod() { XElement person = XElement.Parse("<Person><Name>主神</Name><Age>26</Age></Person>"); Console.WriteLine("{0},{1}", person.Descendants("Name").FirstOrDefault().Value, person.Descendants("Age").FirstOrDefault().Value); } public static void DynamicMethod() { dynamic person = DynamicXmL.Parse("<Person><Name>主神</Name><Age>26</Age></Person>"); Console.WriteLine("{0},{1}", person.Name, person.Age); } } /// <summary> /// 实现自定义的动态对象 /// </summary> public class DynamicXmL : DynamicObject { private XElement element; public DynamicXmL(XElement xElement) { element = xElement; } public static dynamic Parse(string text) { return new DynamicXmL(XElement.Parse(text)); } public override bool TryGetMember(GetMemberBinder binder, out object result) { bool success = false; result = null; 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; } }
View Code
-----------------以上内容根据《C#本质论 第三版》进行整理
相关文章推荐
- Python天天美味(12) - 条件判断的缩写
- 12 个有效的提高编程技能的方法
- Step into Kotlin - 12 - Object 与枚举
- 【MyBatis学习12】MyBatis中的一级缓存
- 个人冲刺12
- 12
- PHP学习笔记(12)程序之外
- cocos2d-x游戏实例(12)-实时拖动主角移动
- Oracle 12cR1 RAC 在VMware Workstation上安装(下)—静默安装
- ca02/ca12 Material Assignment(ca02/ca12分配物料)
- Spark研究笔记12:监听类
- MyBatis知多少(12)私有数据库
- 《C#精彩实例教程》小组阅读12 -- C#面向对象技术高级应用
- 12,javase代码实战-循环控制——用while计算1+1/ 2!+1/ 3!+....+1/ 10!(三)
- 决定你是富人还是穷人的12法则
- 解决UR 12后ISV目录不能用的问题
- TCP/IP详解学习笔记(12)-TCP的超时与重传
- python技巧(12)
- VMWare12 安装Mac OS系统(图解)