个人网站制作网站,宝山做网站价格,达内网络营销,工商局网站怎么做身份确认VS2010之所以那么强大#xff0c;究其原因是其背后有着强大的C#4.0作为后台支撑。和以往的所有版本相比#xff0c;C#4.0的动态性大大增强——dynamic就是一个非常明显的例子#xff1a;#xff08;一#xff09;dynamic初探#xff1a; 以前因为某些特殊原因#xff0c…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 Funcint, int, double((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 Funcstring(()d.Name;); Console.WriteLine(d.Action()); } 初看这个代码只是简单的读写Name属性毫无稀奇可言。但是你注意哦——你到MSDN——或者你索性new ExpandoObject().Name 试试看有Name和Action这个属性吗——没有啊真的没有嘿奇了怪了既然没有为什么你可以凭空“捏造出一个属性”而且可以给属性赋值并且读取属性内容呢 俗话说的好——天下没有白给的食——微软这个类意在向我们揭露一个惊天的大秘密那就是你可以自定义dynamic类让这个类跟随你的要求动态的改变自己比如增加一个新属性等。我们可以参照MSDN给出一个自定义的ExpandoObjectpublic class SimpleDynamic : DynamicObject { Dictionarystring, object Properties new Dictionarystring, object(); Dictionarystring, object[] Methods new Dictionarystring, object[](); 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) { Methods[binder.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其方法介绍如下参数名称作用说明binderSetMemberBinder类型用于获取动态创建赋值属性的时候“属性名”等一些常见信息如示例中Name获取动态赋值的那个属性。valueobject类型用于获取设置动态属性的那个值。如果需要支持动态创建读属性必须覆盖TryGetMember其参数作用和TrySetMember大致相当只是反作用用于获取某个已有属性的内容并且反向传递给object作为输出结果注意TryGetMember的value是一个out类型。同时这个函数多出一个result类型用于返回已有属性的存储的值NULL抛出异常被认为是错误的。 如果需要动态调用函数并输出结果必须覆盖TryInvokeMember方法此函数比较复杂 参数名称作用说明binderInvokeMemberBinder类型用于获取动态创建函数时候一些与函数相关的属性比如Name是函数名其中还有一个CallInfo内嵌属性您还可以获得ArgumentNamesC#4.0中最新的可选参数的名称通过其ArgumentNameCount获取可选参数名的总个数。 Argsobject[]类型获取动态给函数赋的值。resultobject类型返回动态函数执行的结果Null表示异常。 根据以上表格对照不难读懂我的示例代码——现在假设你是这样调用的1dynamic d new SimpleDynamic();d.Name “Serviceboy”;Console.WriteLine(d.Name);首先创建了一个d的动态类型然后当赋值给Name的时候因为Name是属性所以触发了“TrySetMember”函数该函数自动检查是否已经存在这个属性名如果不存在则将其添加进入一个Dictionary中并将对应赋予的值传递进去保存起来。当使用输出的时候同样地TryGetMember被触发系统检测是否预先创建过这个值如果没有则抛出异常存在的话取出对应的存储value并返回给系统。2dynamic d new SimpleDynamic();Console.WriteLine(d.Say(“Hello!”)); 首先创建了一个d的动态类型当动态创建一个方法的时候系统检测是否包含这个方法名不包含将添加这个方法名到Dictionary保存接着检查参数是否为空不为空把参数赋值给那个函数名作为Key的Dictionary中保存最后使用StringBuilder串起来赋值给result作为输出。下面给出一个比较复杂的例子——自定义的XML创建器仿Jeffery Zhaopublic class XmlCreator : DynamicObject { public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { //如果除了第一个节点是字符串后面都是XElement对象表明此节点是父节点 if (args[1] is XElement) { XElement root new XElement(args[0].ToString()); //把子节点添加到父节点 for (int i 1; i args.Length; i) { root.Add(args[i]); } result root; } //否则是子节点 else { //拷贝所有属性到数组 string[] attributes new string[binder.CallInfo.ArgumentNames.Count]; for (int i 0; i binder.CallInfo.ArgumentNames.Count; i) { attributes[i] binder.CallInfo.ArgumentNames[i]; } //拷贝所有属性值到数组 string[] values new string[args.Length - 1]; for (int i 1; i args.Length; i) { values[i - 1] args[i].ToString(); } XElement subelement new XElement(args[0].ToString()); //属性名称获取 for (int i 0; i attributes.Length; i) { subelement.SetAttributeValue(attributes[i], values[i]); } result subelement; } return result ! null; }}该函数功能是输出任意同时带有属性的节点同时可以嵌套——比如dynamic xmlCreator new XmlCreator();XElement ele xmlCreator.CreateElement(“Books”,xmlCreator(“Book”,name:C#,price:100.50) ); 大家可以自己想一想是怎么一个原理哦。转载于:https://www.cnblogs.com/kevin-top/archive/2010/06/04/1751243.html