• 转: .Net 4.0 ExpandoObject 使用


    本篇文章中就ExpandoObject的基本使用进行一些demo。我们几乎都知道dynamic特性是.net 4.0中一个主要的新特性,而ExpandoObject正是这样的一个动态的类型。ExpandoObject允许我们在实例化之后在运行时进行成员的增加、删除。下面我们来看下基本的使用:

    Adding Members

    1)实例化

    如果需要延迟绑定的话,我们需要用dynamic来定义ExpandpObject的实例化变量,关于dynamic的使用,估计大家都很清楚了。

     

    2)增加属性成员

    01.[TestMethod]
    02.public void ExpandoObjectTest()
    03.{
    04.    dynamic employee = new ExpandoObject();
    05.    employee.FirstName = "Henry";
    06.    employee.LastName = "Cui";
    07.    employee.Age = 23;
    08.    Console.WriteLine("Employee's name :{0} age:{1}",
    09.        employee.FirstName + employee.LastName,
    10.        employee.Age);
    11.}

    测试的结果:

    image

    3)增加Method

    在增加方法的时候,先把成员表现成delegate,先看一个没有参数的无返回值的方法:

     
    02.public void ExpandoObjectTest()
    03.{
    04.    dynamic employee = new ExpandoObject();
    05.    employee.FirstName = "Henry";
    06.    employee.LastName = "Cui";
    07.    employee.Age = 23;
    08.    employee.SayHello = (Action)(() => 
    09.    {
    10.        Console.WriteLine("{0} say "Hello" at {1}",
    11.            employee.FirstName+" "+employee.LastName,
    12.            DateTime.UtcNow.ToString());
    13.    });
    14.    employee.SayHello();
    15.}

    在上面的示例中我们将SayHello定义成委托Action类型,并给了默认方法。

    下面来看一个有参数、有返回值的:

     
    01.[TestMethod]
    02.        public void ExpandoObjectTest()
    03.        {
    04.            dynamic employee = new ExpandoObject();
    05.            employee.FirstName = "Henry";
    06.            employee.LastName = "Cui";
    07.            employee.Age = 23;
    08.            employee.SayHello = (Action)(() => 
    09.            {
    10.                Console.WriteLine("{0} say "Hello" at {1}",
    11.                    employee.FirstName+" "+employee.LastName,
    12.                    DateTime.UtcNow.ToString());
    13.            });
    14.  
    15.            employee.GetSalary = (Func<int, decimal>)((month) => 
    16.            {
    17.                if (month > 8)
    18.                    return 5000;
    19.                return 4000;
    20.            });
    21.            Console.WriteLine("The employee's october salary is :${0}",
    22.                employee.GetSalary(10).ToString());
    23.  
    24.        }

    测试结果:

    image

    上面的例子中是段很简单的逻辑就是超过8月份的时候就返回$5000,呵呵。

    4)增加Event

    在实例中我们定义一个请假事件,员工请假就会上报给经理:

     
    01.[TestClass]
    02.   public class DynamicTest
    03.   {
    04.       [TestMethod]
    05.       public void ExpandoObjectTest()
    06.       {
    07.           dynamic employee = new ExpandoObject();
    08.           employee.FirstName = "Henry";
    09.           employee.LastName = "Cui";
    10.           employee.Age = 23;
    11.           employee.SayHello = (Action)(() => 
    12.           {
    13.               Console.WriteLine("{0} say "Hello" at {1}",
    14.                   employee.FirstName+" "+employee.LastName,
    15.                   DateTime.UtcNow.ToString());
    16.           });
    17.           employee.GetSalary = (Func<int, decimal>)((month) => 
    18.           {
    19.               if (month > 8)
    20.                   return 5000;
    21.               return 4000;
    22.           });
    23.           employee.AskForLeaveEvent = null;
    24.           employee.AskForLeaveEvent += new EventHandler(OnEmployeeLeave);
    25.           employee.AskForLeaveEvent(employee,new EventArgs());
    26.       }
    27.       public void OnEmployeeLeave(object sender, EventArgs e)
    28.       {
    29.           dynamic em = (dynamic)sender;
    30.           Console.WriteLine("Report Manager:{0} is asking for leave", em.FirstName + " " + em.LastName);
    31.       }

    我们看下运行的结果:

    image

    Remove Members

    其实ExpandoObject继承了IDictionary<String, Object>的接口,所以我们枚举出在运行时增加的那些成员.

    1)枚举出已经存在的成员

    我们就来枚举出刚才在employee中增加的成员们:

     
    1.foreach (var pro in (IDictionary<string, Object>)employee)
    2.{
    3.    Console.WriteLine(pro.Key+" "+pro.Value);
    4.}

    我们可以看到测试结果:

    image

    2)移除成员

    其实我们还是利用了ExpandoObject实现了IDictionary接口去实现的,我们移除掉AskForLeaveEvent事件:

     
    1.((IDictionary<string, object>)employee).Remove("AskForLeaveEvent");
    2.foreach (var pro in (IDictionary<string, Object>)employee)
    3.{
    4.    Console.WriteLine(pro.Key+" "+pro.Value);
    5.}

    我们看看运行的结果:

    image

    我们可以看到AskForLeaveEvent被移除了。

    总结

    本文中主要介绍了ExpandoObject的基本使用,我们发现真的有点动态语言的风味,写过javascript的人感觉会太别爽,呵呵。下文中会就ExpandoObject的原理以及一些扩展就行一些说明。

    本篇文章就ExpandoObject的一些高级的使用进行一些示例。

    例子

    首先要说的一点,为什么我们在定义动态类型的ExpandoObject时,必须要使用dynamic关键字呢,因为如果我们使用ExpandoObject 进行定义时,那么我们定义的变量就是一个静态类型ExpandoObject的实例化。

    下面我们来做个例子就是如何将xml的表示成面向对象的形式。其实在c#3.0中已经提供了Linq To Xml的方式让我们来操作xml,确实比以前的dom方式方便了很多,但是觉得还是看着不太优雅。我们先来看一个Linq To Xml的示例:

    private XElement CreateByXelement()
    {
    var xelement = new XElement(
    "Employee",
    new XElement("FirstName","Henry"),
    new XElement("LastName","Cui"),
    new XElement("Age",23),
    new XElement(
    "Company",
    new XElement("Name","XXXX"),
    new XElement("Address","Suzhou China")
    )
    );
    return xelement;
    }

    这种方式我觉得是比以前的dom方式更为直观了,但是希望能够以更加优雅的方式来表示:

     private dynamic CreateByExpandoObject()
    {
    dynamic employee = new ExpandoObject();
    employee.FistName="Henry";
    employee.LastName="Cui";
    employee.Age=23;
    employee.Company = new ExpandoObject();
    employee.Company.Name="XXXX";
    employee.Company.Address="Suzhou China";
    return employee;
    }

    转换

    也许现在最大的疑问就是想XElement一样提供了Save方法,这里我们来写些辅助的方法进行ExpandoObject到xml的转换吧:

    private XElement ConvertExpandoObjectToXelement(string eleName, dynamic node)
    {
    var xNode = new XElement(eleName);
    foreach (var pro in (IDictionary<string, object>)node)
    {
    if (pro.Value is ExpandoObject)
    {
    xNode.Add(ConvertExpandoObjectToXelement(pro.Key, pro.Value));
    }
    else
    {
    xNode.Add(new XElement(pro.Key, pro.Value));
    }
    }
    return xNode;
    }

    来看看一个测试:

    [TestMethod]
    public void TestExpandoConvert()
    {
    var element = ConvertExpandoObjectToXelement("Employee",
    CreateByExpandoObject());
    Console.WriteLine(element.ToString());
    }

    我们看到输出结果:

    image

    好像有点大功告成了,其实远没有这么简单。我们来考虑几个问题,首先如果出现重复的节点怎么办,比如Employee受聘用。我们可以List结合来表示:

    private dynamic CreateByExpandoObject()
    {
    dynamic employee = new ExpandoObject();
    employee.FistName="Henry";
    employee.LastName="Cui";
    employee.Age=23;
    employee.Company = new List<dynamic>();
    employee.Company.Add(new ExpandoObject());
    employee.Company[0].Name = "XXXX";
    employee.Company[0].Address = "Suzhou China";
    employee.Company.Add(new ExpandoObject());
    employee.Company[1].Name = "YYYY";
    employee.Company[1].Address = "Suzhou China";
    return employee;
    }

    然后我们修改下转换增加对List<dynamic>类型的处理:

    private XElement ConvertExpandoObjectToXelement(string eleName, dynamic node)
    {
    var xNode = new XElement(eleName);
    foreach (var pro in (IDictionary<string, object>)node)
    {
    if (pro.Value is ExpandoObject)
    {
    xNode.Add(ConvertExpandoObjectToXelement(pro.Key, pro.Value));
    }
    else
    {
    if (pro.Value is List<dynamic>)
    {
    foreach (var child in (List<dynamic>)pro.Value)
    {
    xNode.Add(ConvertExpandoObjectToXelement(pro.Key, child));
    }
    }
    else
    {
    xNode.Add(new XElement(pro.Key, pro.Value));
    }
    }
    }
    return xNode;
    }

    来看看测试的效果:

    image

    API的支持

    1)查询

    在Linq To Xml中提供了比如:Element、Elements、Descendant、Descendants方法来查询。

    而对于我们使用ExpandoObject可以这样:对于单个的属性我们直接通过对象的属性去访问就可以得到了,对于List类型的我们可以使用Linq的语法:

     var company = from c in (List<dynamic>)CreateByExpandoObject().Company
    where c.Name == "XXXX"
    select c;
    Console.WriteLine(company.First().Name);

    2)修改

    对于简单属性的修改直接通过对象的属性就可以去修改了,而对于List<dyniamic>类型:

     foreach (var child in (List<dynamic>)CreateByExpandoObject().Company)
    {
    if (child.Name == "XXXX")
    {
    child.Address = "Shanghai China";
    }
    }

     

    总结

    本文就如何使用ExpandoObject在xml领域中的使用进行了一些示例,只是一个初略的demo,不能说是解决方案。其实我们还可以通过dynamic库中的另外一个类型DynamicObject来实现,实现起来更为优雅,更为方便。在下文中会就DynamicObject操作xml进行一些尝试。

    转自:http://henllyee.cnblogs.com/

  • 相关阅读:
    Mac下的类似apt-get的包管理工具Homebrew(笔记)
    C# 通过模拟http请求来调用soap、wsdl
    提高 ASP.NET Web 应用性能
    Ajax ContentType 列表大全
    关于多核游览器指定渲染内核的方法。
    Aspx页面模拟WebService功能
    Dapper完美兼容Oracle,执行存储过程,并返回结果集。
    简单爬虫,突破IP访问限制和复杂验证码,小总结
    在子线程中创建新的窗体,遇到的问题。
    【干货】jsMind思维导图整合Easyui的右键菜单
  • 原文地址:https://www.cnblogs.com/yangfantianxia/p/6510552.html
Copyright © 2020-2023  润新知