资源预览内容
第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
第9页 / 共10页
第10页 / 共10页
亲,该文档总共10页全部预览完了,如果喜欢就下载吧!
资源描述
VS2010之所以那么强大,究其原因是其背后有着强大的C#4.0作为后台支撑。和以往的所有版本相比,C#4.0的动态性大大增强dynamic就是一个非常明显的例子:(一)dynamic初探:以前因为某些特殊原因,需要动态的调用外部类(假设这个类是实现了某个带有参数的接口函数的),通常我们只能用反射了。示例代码如下:Assembly asm = Assembly.LoadFile(“xxxxx”)asm.CreateInstance(MyAssembly.ClassName).GetType().InvokeMember(Say, BindingFlags.InvokeMethod, null, asm.CreateInstance(MyAssembly.ClassName ), new string aaa );这里顺便简略说一下反射流程:首先通过绝对路径加载某个NET的dll文件,然后创建该assembly中某个class的instance(该 class必须有无参构造函数),获取其类型之后动态调用其函数Say,“BindingFlags.InvokeMethod”表明是一个普通类方 法,“null”的地方是传递一个参数名的,和指明最后的string中的一串values内容一一匹配的可见使用反射调用函数是很痛苦的一件事 情。现在呢?您根本不需要那么麻烦了!因为C#的dynamic会为您做好一切的,下面就是见证奇迹的时刻Assembly asm = Assembly.LoadFile(xxxxx);dynamic dfun = asm.CreateInstance(MyAssembly.ClassName);dfun.Say(Hello!); 注意到咖啡色的代码了么什么?dynamic竟然可以智能感知出动态加载的那个类的方法Say?其实不然:当你按下这个点的时候,IDE是没有智能感 知的,但是如果你知道这个类是有这个方法(因为接口给了其一个契约,必须实现接口中的方法;而接口的方法是公开的),你就可以完全不理会智能感知,照样 写,照样编译通过运行。神奇吧! 看到这里,你就不会认为dynamic和var是“差不多”的概念了(var无非是根据赋值的类型编译器自己判断;且var不能作为函数返回值类型,但是dynamic可以)。 或许有人会疑问:dynamic可以完全替代类似像简单工厂、抽象工厂一类的东西了咯?我的理解是不对!从上面的定义中可以得知:dynamic必须首先获取对象实例,然后动态反射是它做的事情;如果完全取代反射,实例也获取不到,如何反射呢?真是“巧妇难为无米之炊”啊! 说道dynamic可以作为返回值,下面给出一个例子:class DynamicClass public int Num1 get; set; public int Num2 get; set; public DynamicClass(int n1, int n2) Num1 = n1; Num2 = n2; public dynamic DynamicAction get; set; 主函数注意咖啡色部分:static void Main(string args) DynamicClass t = new DynamicClass(1, 2); t.DynamicAction = new Func(x, y) = x + y); Console.WriteLine(t.DynamicAction.Invoke(t.Num1,t.Num2); 道理很简单:因为dynamic类型可以赋值任何东西(包括匿名委托),所以我创建了一个匿名委托给它。然后调用计算结果(匿名委托的调用使用Invoke,可以省略)。 但是dynamic不仅仅可以动态反射类方法和属性,还可以“空中楼阁”般动态地去创建一个类方法和属性,并且赋值,相信吗?这是第二话。(二)神奇的ExpandoObject类和自定义动态类扩展:dynamic在第一话中已经展示它动态根据赋值类型直接自动完成反射的强大功能。现在又是一个新奇迹的诞生static void Main(string args) dynamic d = new ExpandoObject(); d.Name = ServiceBoy; d.Action = Func()=d.Name;); Console.WriteLine(d.Action(); 初看这个代码只是简单的读写Name属性,毫无稀奇可言。但是你注意哦你到MSDN或者你索性new ExpandoObject().Name 试试看,有Name和Action这个属性吗?没有啊,真的没有!嘿,奇了怪了,既然没有,为什么你可以凭空“捏造出一个属性”,而且可以给属性赋 值,并且读取属性内容呢? 俗话说的好天下没有白给的食微软这个类意在向我们揭露一个惊天的大秘密,那就是你可以自定义dynamic类,让这个类跟随你的要求动态的改变自 己(比如增加一个新属性等)。我们可以参照MSDN,给出一个自定义的ExpandoObject:public class SimpleDynamic : DynamicObject Dictionary Properties = new Dictionary(); Dictionary Methods = new Dictionary(); public override bool TryInvokeMember(InvokeMemberBinder binder, object args, out object result) if (!Methods.Keys.Contains(binder.Name) Methods.Add(binder.Name, null); if (args != null) Methodsbinder.Name = args; StringBuilder sbu = new StringBuilder(); foreach (var item in args) sbu.Append(item); result = sbu.ToString(); return true; public override bool TrySetMember(SetMemberBinder binder, object value) if (!Properties.Keys.Contains(binder.Name) Properties.Add(binder.Name, value.ToString(); return true; public override bool TryGetMember(GetMemberBinder binder, out object result) return Properties.TryGetValue(binder.Name, out result); 首先说明这个例子的作用:随意增加不重复的属性并赋值(取值),并且让你随意创建或者调用(带参或无参)函数进行输入(输出)。 分析一下这个类的主要特点: 一般地,任何一个类如果需要动态为自身添加属性、方法等的,就必须实现IDynamicObjectProvidor接口或者是 DynamicObject虚类(之所以用虚类的原因是“各取所需”的缘故,DynamicObject类都通过虚方法virtual去“实现”了接口中 所有的方法,只要继承了这个类,读者可以根据需要“任意”动态覆盖你要的方法)。这里介绍三个最常见的方法: 如果需要支持动态创建写属性,必须覆盖TrySetMember,其方法介绍如下:参数名称作用说明binder:SetMemberBinder类型用于获取动态创建赋值属性的时候“属性名”等一些常见信息(如示例中Name获取动态赋值的那个属性)。value:object类型用于获取设置动态属性的那个值。 如果需要支持动态创建读属性,必须覆盖TryGetMember,其参数作用和TrySetMember大致相当,只是反作用(用于获取某个已有 属性的内容,并且反向传递给object作为输出结果,注意TryGetMember的value是一个out类型)。同时,这个函数多出一个 result类型,用于返回已有属性的存储的值(NULL抛出异常,被认为是错误的)。 如果需要动态调用函数并输出结果,必须覆盖TryInvokeMember方法,此函数比较复杂:参数名称作用说明binder:InvokeMemberBinder类型用于获取动态创建函数时候一些与函数相关的属性:(比如Name是函数名,其中还有一个CallInfo内嵌属性,您还可以获得ArgumentNames(C#4.0中最新的可选参数的名称,通过其ArgumentNameCount获取可选参数名的总个数)。Args:object类型获取动态给函数赋的值。result:object类型返回动态函数执行的结果,Null表示异常。根据以上表格,对照不难读懂我的示例代码现在假设你是这样调用的:1)dynamic d = new SimpleDynamic();d.Name = “Serviceboy”;Console.WriteLine(d.Name);首先创建了一个
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号