publicclassCommandLineSwitchAliasAttribute:Attribute{publicCommandLineSwitchAliasAttribute(stringalias){
Alias =alias;}publicstring Alias{get;privateset;}}classCommandLineInfo{[CommandLineSwitchAlias("?")]publicbool Help {get;set;}}
[Serializable]classEncryptableDocument:ISerializable{enum Field
{
Title,
Data
}publicstring Title;publicstring Data;publicvoidGetObjectData(SerializationInfo info,StreamingContext context){
info.AddValue(Field.Title.ToString(),Title);
info.AddValue(Field.Data.ToString(),Data);}publicEncryptableDocument(SerializationInfo info,StreamingContext context){
Title = info.GetString(Field.Title.ToString());
Data = info.GetString(Field.Data.ToString());}}
17.2.3.4.4 OptionalFieldsAttribute
作用
将字段标注为可选序列化字段
向后兼容实现版本控制
当原始类型中新增字段后,从已序列化的文件中反序列化得到对象会抛出异常,可以用该特性标注为可选字段
伪特性
包括大部分预定义特性在CIL代码中出现在类定义的内部
Serializable特性出现在元数据表的设置位
17.3 使用动态对象进行编程
17.3.1 dynamic
dynamic的概念
编译器将有关语句的预期作用的信息一起打包到类型化为 dynamic 的对象或表达式
在运行时,对存储的信息进行检查,任何无效的语句会导致运行 时异常。
如果没有任何调用,dynamic类型声明和object没有区别
一旦调用其成员,会再编译一段代码并注入调用点
dynamic的作用
类型转换
dynamic可以隐式转化为任意类型
任意类型也可隐式转化为dynamic
简化反射
在Type类型上查找并调用成员的过程可以简化为直接调用成员
效率比直接使用反射高
动态编译
直接注入到调用点
后续调用没有反射和编译开销
publicclassExample{publicstaticvoidMain(){ObjectHandle handle = Activator.CreateInstance("PersonInfo","Person");/*
Object p = handle.Unwrap();
Type t = p.GetType();
MethodInfo method = t.GetMethod("ToString");
Object retVal = method.Invoke(p, null);
*/dynamic p = handle.Unwrap();Object retVal = p.ToString();}}
17.3.2 动态绑定
概念
在编译时,根据类无法分析出其包含的具体成员,需要在运行时才能真正分析出来
作用
将类型、成员和操作的解析过程从编译时延迟到运行时
静态编译的优点是类型安全,但当静态编译无法真正发挥作用时,静态编译和动态绑定的功能没有差别
简化代码编写
XELement person = XElement.Parse(@"<person>
<FirstName>Inigo</FirstName>
</person>");//根据XELment类无法分析出其具有的成员
Console.WriteLine(person.Descendants("FirstName").FirstOrDefault().Value);dynamic person = DynamicXml.Parse(@"<person>
<FirstName>Inigo</FirstName>
</person>");
Console.WriteLine(person.FirstName);