Ruby中有个很好用的XML API,在页面实现XML输出很方便。比如有个联系人Contacts的XML输出,Ruby里面是这样写的。

...
xml.contacts doxml.contact(:type => "work") doxml.name("Joe Smith")end
end
...

借用.Net 4.0的dynamic特性,用C#实现一个XmlBuilder。测试代码如下:

XmlBuilderTest

[TestFixture]
public class XmlBuilderTest
{
[Test]
public void CreatorTest()
{
dynamic xmlBuilder = new XmlBuilder();
var result = xmlBuilder.Contacts(
xmlBuilder.Contact("type", "team-member", "id", "1",
xmlBuilder.Name("Joe Smith"),
xmlBuilder.Phone("type", "work", "(123) 456-7890"),
xmlBuilder.爱好("看电影"),
xmlBuilder.Address("type", "home",
xmlBuilder.Street("123 Main St."),
xmlBuilder.City("SpringField"))));

Console.WriteLine("XML: \n" + result.ToString());
}

}

为实现上述功能,我们创建类XmlBuilder,继承DynamicObject,并override其TryInvokeMember方法。

XmlBuilder

public class XmlBuilder : DynamicObject
{
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
var arguments = ParseArguments(args);
var rootElement = new XElement(binder.Name, arguments.Text, arguments.Attributes);
foreach (XDocument xDocument in arguments.Documents)
rootElement.Add(xDocument.FirstNode);

result = new XDocument(rootElement);
return true;
}

private static dynamic ParseArguments(object[] arguments)
{
var documents = new List<XDocument>();
var strings = new List<string>();
var attributes = new List<XAttribute>();
string text = null;

//分析参数类型,区分string和XDocument
foreach (var arg in arguments)
{
XDocument xDocArgument;
string stringArgument;
if (CastAs(arg, out xDocArgument))
documents.Add(xDocArgument);
else if (CastAs(arg, out stringArgument))
strings.Add(stringArgument);
}

//如果strings总数为奇数,定义最末一个字符串为InnerText。
if (strings.Count % 2 == 1)
{
text = strings.Last();
strings.RemoveAt(strings.Count - 1);
}

//将strings成对封装为XAttribute。
for (var i = 0; i < strings.Count; i=i+2)
{
attributes.Add(new XAttribute(strings[i], strings[i+1]));
}

//返回动态类型。
return new { Documents = documents, Attributes = attributes, Text = text };
}

/// <summary>
/// 类型判断
/// </summary>
private static bool CastAs<T>(object value, out T castedValue)
{
if (value is T)
{
castedValue = (T)value;
return true;
}
castedValue = default(T);
return false;
}
}

运行XmlBuilderTest,得到的结果如下:

XML:
<Contacts>
<Contact type="team-member" id="1">
<Name>Joe Smith</Name>
<Phone type="work">(123) 456-7890</Phone>
<爱好>看电影</爱好>
<Address type="home">
<Street>123 Main St.</Street>
<City>SpringField</City>
</Address>
</Contact>
</Contacts>

-- 声明 --

1、没太动脑筋,主要的实现思路(包括部分代码),来源于In a Perfect World。(带梯子可访问)原作者给的代码有问题,我在上面做了修改。

2、运行dynamic,需要在.Net 4.0环境下,引用程序集Microsoft.CSharp.dll。

-- 下载 --

所有代码在这儿下载。XmlBuilderTest.zip

转载于:https://www.cnblogs.com/workingbird/articles/CSharp_dynamic_xmlbuilder_like_ruby.html

用C#实现仿Ruby的XML Builder相关推荐

  1. 常用ruby gem

    常见gems: Devise 用于快速构建用户功能,如:注册,登陆,个人设置,找回密码 oauth OmniAuth 如果你需要在项目中实现三方平台(如: Twitter, Facebook, 新浪微 ...

  2. Ruby on Rails 之旅(七)—— Ruby on Rails 入门(5)

    为什么80%的码农都做不了架构师?>>>    接下来我们一起学习一下respond_to 字面意思是响应给...我们可以理解为,你要什么格式. 以往一样的操作返回不同的格式,我们大 ...

  3. xml 和android脚本之家,Android利用Document实现xml读取和写入操作

    本文实例为大家分享了利用Document实现xml读取和写入操作,供大家参考,具体内容如下 首先先来介绍一下什么xml?xml是可扩展标记语言,他可以用来标记数据,定义数据类型.是一种允许用户对自己标 ...

  4. Spring Boot 2.x基础教程:如何扩展XML格式的请求和响应

    在之前的所有Spring Boot教程中,我们都只提到和用到了针对HTML和JSON格式的请求与响应处理.那么对于XML格式的请求要如何快速的在Controller中包装成对象,以及如何以XML的格式 ...

  5. Spring Boot中如何扩展XML请求和响应的支持

    在之前的所有Spring Boot教程中,我们都只提到和用到了针对HTML和JSON格式的请求与响应处理.那么对于XML格式的请求要如何快速的在Controller中包装成对象,以及如何以XML的格式 ...

  6. Spring Boot中扩展XML请求和响应的支持

    在Spring Boot中,我们大多时候都只提到和用到了针对HTML和JSON格式的请求与响应处理.那么对于XML格式的请求要如何快速的在Controller中包装成对象,以及如何以XML的格式返回一 ...

  7. ruby 读取文本_使用Ruby进行文本处理

    ruby 读取文本 在与Perl或Python相同的页面上,Ruby具有强大的功能,可以成为强大的文本处理语言. 本文简要地讨论了Ruby的文本数据处理能力,以及如何使用它来有效处理文本数据的不同格式 ...

  8. 3分钟教你实现仿微信底部导航栏效果(BottomNavigationView + ViewPager)

    文章目录 实现效果图 前言 XML布局 menu文件 ViewPager的使用 PagerAdapter(Java) Activity中实现 上下联动 侧滑带动按钮选择 点击底部按钮带动页面 自定义选 ...

  9. Rails5 Controller Document

    更新: 2017/06/28 大致完成全部 更新: 2017/06/29 补充module文件命名规则 更新: 2017/07/09 补充session的设置 更新: 2018/03/06 修正ren ...

最新文章

  1. java.io几种读写文件的方式
  2. ASP.NET Core 上传多文件 超简单教程
  3. 【渝粤题库】国家开放大学2021春2509学前教育学题目
  4. 【转来警醒自己】最近的一些面试感悟
  5. 微软免费软件项目DreamSpark更名为Microsoft Imagine
  6. 一文领略 HTTP 的前世今生
  7. linux 中的MYSQL命令汇总
  8. 转载------工作10年的人总结的6句话
  9. 7限制cpu使用_macOS限制CPU或进程使用率
  10. python:关于三级菜单的新手实现
  11. 图文并茂超详细搭建memcache缓存服务器(nginx+php+memcache+mysql)
  12. jetson nano opencv 打开 CSI摄像头_opencv-python图形图像处理入门基础知识
  13. TFT-LCD与FSMC控制器
  14. 综合布线:如何选择多模光纤和单模光纤
  15. 基于DDD的微服务设计和开发实战
  16. 人口红利消失,电销要怎么做才能立足市场?
  17. C语言七巧板游戏制作,绘本里的七巧板游戏
  18. soul网关mysql8_深度解析 Soul 网关——数据同步
  19. 解析飞凌嵌入式i.MX8MM在智慧医疗麻醉系统中的应用方案
  20. nodejs读取服务器json文件,nodejs读写json文件的简单方法(必看)

热门文章

  1. 微课视频小学用计算机画画,初识电脑绘画
  2. 计算机课题推荐人意见,课题推荐人意见怎么写
  3. 用-force –opengl 指令_OpenGL-使用Tessellation技术绘制Cubic Bézier Patches
  4. python numpy库等差不均分_numpy.linspace 生成等差数组的方法
  5. 分享3个干货满满的Python实战项目,点赞收藏
  6. 13个Pandas实用技巧,有点香 !
  7. 太难得了!大厂数据分析实战项目资料首次公开!免费,速领!
  8. 什么叫计算机网络阻塞,计算机网络中的“线端阻塞”释义
  9. php mysql查询时间_php查询时间段 mysql时间查询
  10. 数据分析学习01-matplotlib绘图工具基本操作