zoukankan      html  css  js  c++  java
  • 浅谈C#4 Dynamic

    Dynamic关键字和DLR是C#4和.NET Framework 4中重大的新增功能!

    1.什么是“动态”?

    一般而言,动态语言不执行编译时类型检查,仅在运行时识别对象的类型。缺少编译时类型检查也会导致 IntelliSense 功能无效。

    C# 最初是作为纯静态语言创建的,但 C# 4 添加了一些动态元素,用以改进与动态语言和框架之间的互操作性。C# 团队考虑了多种设计选项,但最终确定添加一个新关键字来支持这些功能:dynamic。

    当我们使用 dynamic 关键字时,我们就告诉了编译器关闭编译时检查。网上以及 MSDN 文档中有大量关于如何使用该关键字的示例。

    2.Dynamic、Object 、Var区别

    关键字 object 表示 System.Object 类型,它是 C# 类层次结构中的根类型。此关键字经常在编译时无法确定对象类型时使用,而这种情况经常在各种互操作性情形中发生。

    从 C# 3.0 起,关键字 var 开始用于隐式类型化局部变量以及匿名类型。此关键字经常与 LINQ 结合使用。当使用 var 关键字声明变量时,将在编译时根据初始化字符串推断该变量的类型。在运行时无法更改该变量的类型。如果编译器不能推断类型,它会生成一个编译错误。

    C# 4 中引入的 dynamic 关键字可使某些传统上依赖于 object 关键字的情形更容易编写和维护。实际上,动态类型在后台使用 System.Object 类型。但与 object 不同的是,动态类型不需要在编译时执行显式转换操作,因为它仅在运行时识别类型。

    3.Dynamic一般用法示例

    基本的用法,用代码来说吧:

    using System;
    using System.Reflection;
    
    namespace csdlr
    {
        public class Employee
        {
            public string FirstName { get; set; }
    
            public void Speak()
            {
                Console.WriteLine("My name is {0}", FirstName);
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                ////Error 1:
                //var o_1 = GetASpeaker();
                //o_1.Speak();
                ////Error 2:
                //object o_2 = GetASpeaker();
                //o_2.Speak();
    
                //1.普通
                Employee o = GetASpeaker() as Employee;//var o=GetASpeaker();//OK also.
                o.Speak();
                //2.反射
                object o1 = GetASpeaker();
                o1.GetType().GetMethod("Speak").Invoke(o, null);
                //3.Dynamic
                dynamic o2 = GetASpeaker();
                o2.Speak();
    
                Console.ReadKey();
                //程序并未添加Dogs这个程序集的引用,其和可执行程序在同一目录下即可
                //反射程序集,动态创建其类型实例,并调用其方法
                Type dogType = Assembly.Load("Dogs").GetType("Dogs.Dog");//注意:完全限定名,困惑了好久!
                dynamic dog = Activator.CreateInstance(dogType);
                dog.Speak();
    
                Console.ReadKey();
    
            }
    
            private static object GetASpeaker()
            {
                return new Employee() { FirstName = "DebugLZQ" };
            }
        }
    }

    Dogs类库如下:

    View Code
    using System;
    
    namespace Dogs
    {
        public class Dog
        {
            public void Speak()
            {
                Console.WriteLine("Woof");
            }
        }
    }

    其编译后为Dogs.dll。

    4.Dynamic关键字

    using System;
    using System.Dynamic;
    
    namespace ExpandoSample
    {
        class Program
        {
            static void Main(string[] args)
            {
                //ExpandoObject:表示一个对象,该对象包含可在运行时动态添加和移除的成员。
                dynamic expando=new ExpandoObject();
                expando.Name = "DebugLZQ";
                expando.Speak = new Action(()=>Console.WriteLine("My name is {0}",expando.Name ));
    
                expando.Speak();
    
                Console.ReadKey();
            }
        }
    }

    要了解更加深入的方案,请看关于 ExpandoObjectDynamicObject 类的 MSDN 文档。同时,还有一些值得一看的文章,比如由 Bill Wagner 撰写的文章“动态方法包

    5.动态功能与 COM 互操作

    C# 团队在 C# 4 版本中专门考虑的 COM 互操作方案是针对 Microsoft Office 应用程序(如 Word 和 Excel)进行编程。他们的目的是让这一任务在 C# 中变得像在 Visual Basic 中那样容易和自然。

    using System;
    using System.Diagnostics;
    
    namespace dynamicExcel
    {
        class Program
        {
            static void Main(string[] args)
            {
                Type excelType = Type.GetTypeFromProgID("Excel.Application");
                dynamic excel = Activator.CreateInstance(excelType);
    
                excel.Visible = true;
                excel.Workbooks.Add();
    
                dynamic sheet = excel.ActiveSheet;
    
                Process[] processes = Process.GetProcesses();
                for (int i = 0; i < processes.Length ; i++)
                {
                    sheet.Cells[i + 1, "A"] = processes[i].ProcessName;
                    sheet.Cells[i + 1, "B"] = processes[i].Threads.Count;
                }
            }
        }
    }

     

    6.类包装

    使用它可以为自己的库提供更好的语法,或为现有库创建包装。

    using System;
    using System.Xml.Linq;
    
    namespace EncodXML
    {
        class Program
        {
            static void Main(string[] args)
            {
                //处理XML基本就这三种框架
                //1.XmlDocument
                //...
                //2.LINQ to XML
                //...
                //3.XDocument
                var doc = XDocument.Load("Employees.xml");
                foreach (var employee in doc.Element("Employees").Elements("Employee"))
                {
                    Console.WriteLine(employee.Element("FirstName").Value );
                }
    
                //Dynamic包装-提供更简洁的语法
                var doc2 = XDocument.Load("Employees.xml").AsExpando();
                foreach (var employee in doc2.Employees)
                {
                    Console.WriteLine(employee.FirstName);
                }
            }
        }
    }
    using System.Collections.Generic;
    using System.Linq;
    using System.Xml.Linq;
    using System.Dynamic;
    
    namespace EncodXML
    {
        public static class ExpandoXML
        {
            public static dynamic AsExpando(this XDocument xDocument)
            {
                return CreateExpando(xDocument.Root);
            }
    
            private static dynamic CreateExpando(XElement element)
            {
                var result = new ExpandoObject() as IDictionary<string, object>;
                if(element.Elements().Any(e=>e.HasElements ))
                {
                    var list = new List<ExpandoObject>();
                    result.Add(element.Name.ToString(),list);
                    foreach(var childElement in element.Elements())
                    {
                       list.Add(CreateExpando(childElement )); 
                    }
                }
                else
                {
                    foreach (var leafElement in element.Elements())
                    {
                       result.Add(leafElement.Name.ToString(),leafElement.Value ); 
                    }
                }
                return result;
            }
        }
    }
    View Code
    <?xml version="1.0" encoding="utf-8" ?>
    <Employees>
      <Employee>
        <FirstName>DebugLZQ</FirstName>
      </Employee>
      <Employee>
        <FirstName>DebugLZQ</FirstName>
      </Employee>
      <Employee>
        <FirstName>DebugLZQ</FirstName>
      </Employee>
      <Employee>
        <FirstName>DebugLZQ</FirstName>
      </Employee>
      <Employee>
        <FirstName>DebugLZQ</FirstName>
      </Employee>
      <Employee>
        <FirstName>DebugLZQ</FirstName>
      </Employee>
    </Employees>

    其他

    关于反射与Dynamic使用方法对照

    using System;
    using System.Reflection;
    
    namespace LoadAssembly
    {
        class Program
        {
            static void Main(string[] args)
            {
                Type dogType = Assembly.Load("Dogs").GetType("Dogs.Dog");
                dynamic dog = Activator.CreateInstance(dogType);
                dog.Speak();
                Console.ReadKey();
    
                object dog2 = Activator.CreateInstance(dogType);
                dog2.GetType().GetMethod("Speak").Invoke(dog2, null);             
                Console.ReadKey();
            }
        }
    }

    关于Dynamic优化反射性能请看:浅谈.NET反射机制的性能优化。 

  • 相关阅读:
    关于element-ui表格样式设置的方法cell-class-name
    Js中JSON.stringify()与JSON.parse()与eval()详解及使用案例
    Bootstrap switch 切换状态踩坑
    字符串数组去重
    java效率取随机不重复数
    List 的add()与addAll()的区别
    在HTML中限制input 输入框只能输入纯数字
    抽象类继承接口
    IOC容器之Autofac
    浅拷贝和深拷贝
  • 原文地址:https://www.cnblogs.com/DebugLZQ/p/2980939.html
Copyright © 2011-2022 走看看