我正在寻找一种将对象树转换为 XML 的方法。写起来会很有趣,但我相信已经有人写过了。这是我的愿望 list :
我不需要重建对象模型,所以只写解决方案很好(可能是预期的)。
我认为折扣:
最佳答案
罗伯特·罗斯尼 (Robert Rossney) 的帖子让我觉得这可能比我想象的要简单。所以这是一个非常粗略的尝试。它处理以下内容:
这是一个输出示例(在我的测试对象中,订单上的“货币”产品抛出异常)。
<Customer Ref="1">
<FirstName>Paul</FirstName>
<LastName>Stovell</LastName>
<FullName>Paul Stovell</FullName>
<Orders>
<Order Ref="2">
<SKU>Apples</SKU>
<Price>27.30</Price>
<Currency>Something bad happened</Currency>
<Customer Ref="1" />
</Order>
<Order Ref="3">
<SKU>Pears</SKU>
<Price>17.85</Price>
<Currency>Something bad happened</Currency>
<Customer Ref="1" />
</Order>
<Order Ref="2" />
</Orders>
</Customer>
下面是示例对象模型和用法:
static void Main(string[] args)
{
var customer = new Customer();
customer.FirstName = "Paul";
customer.LastName = "Stovell";
customer.Orders.Add(new Order(customer) { Price = 27.30M, SKU = "Apples"});
customer.Orders.Add(new Order(customer) { Price = 17.85M, SKU = "Pears"});
customer.Orders.Add(customer.Orders[0]);
var output = new StringWriter();
var writer = new XmlTextWriter(output);
writer.Formatting = Formatting.Indented;
WriteComplexObject("Customer", customer, writer);
Console.WriteLine(output.ToString());
Console.ReadKey();
}
class Customer
{
private readonly List<Order> _orders = new List<Order>();
public Customer()
{
}
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
// Read-only property test
get { return FirstName + " " + LastName; }
}
public List<Order> Orders
{
// Collections test
get { return _orders; }
}
}
class Order
{
private readonly Customer _customer;
public Order(Customer customer)
{
_customer = customer;
}
public string SKU { get; set; }
public decimal Price { get; set; }
public string Currency
{
// A proprty that, for some reason, can't be read
get
{
throw new Exception("Something bad happened");
}
}
public Customer Customer
{
get { return _customer; }
}
}
实现如下:
public static void WriteObject(string name, object target, XmlWriter writer)
{
WriteObject(name, target, writer, new List<object>(), 0, 10, -1);
}
private static void WriteObject(string name, object target, XmlWriter writer, List<object> recurringObjects, int depth, int maxDepth, int maxListLength)
{
var formatted = TryToFormatPropertyValueAsString(target);
if (formatted != null)
{
WriteSimpleProperty(name, formatted, writer);
}
else if (target is IEnumerable)
{
WriteCollectionProperty(name, (IEnumerable)target, writer, depth, maxDepth, recurringObjects, maxListLength);
}
else
{
WriteComplexObject(name, target, writer, recurringObjects, depth, maxDepth, maxListLength);
}
}
private static void WriteComplexObject(string name, object target, XmlWriter writer, List<object> recurringObjects, int depth, int maxDepth, int maxListLength)
{
if (target == null || depth >= maxDepth) return;
if (recurringObjects.Contains(target))
{
writer.WriteStartElement(name);
writer.WriteAttributeString("Ref", (recurringObjects.IndexOf(target) + 1).ToString());
writer.WriteEndElement();
return;
}
recurringObjects.Add(target);
writer.WriteStartElement(name);
writer.WriteAttributeString("Ref", (recurringObjects.IndexOf(target) + 1).ToString());
foreach (var property in target.GetType().GetProperties())
{
var propertyValue = ReadPropertyValue(target, property);
WriteObject(property.Name, propertyValue, writer, recurringObjects, depth + 1, maxDepth, maxListLength);
}
writer.WriteEndElement();
}
private static object ReadPropertyValue(object target, PropertyInfo property)
{
try { return property.GetValue(target, null); }
catch (Exception ex) { return ReadExceptionMessage(ex); }
}
private static string ReadExceptionMessage(Exception ex)
{
if (ex is TargetInvocationException && ex.InnerException != null)
return ReadExceptionMessage(ex.InnerException);
return ex.Message;
}
private static string TryToFormatPropertyValueAsString(object propertyValue)
{
var formattedPropertyValue = null as string;
if (propertyValue == null)
{
formattedPropertyValue = string.Empty;
}
else if (propertyValue is string || propertyValue is IFormattable || propertyValue.GetType().IsPrimitive)
{
formattedPropertyValue = propertyValue.ToString();
}
return formattedPropertyValue;
}
private static void WriteSimpleProperty(string name, string formattedPropertyValue, XmlWriter writer)
{
writer.WriteStartElement(name);
writer.WriteValue(formattedPropertyValue);
writer.WriteEndElement();
}
private static void WriteCollectionProperty(string name, IEnumerable collection, XmlWriter writer, int depth, int maxDepth, List<object> recurringObjects, int maxListLength)
{
writer.WriteStartElement(name);
var enumerator = null as IEnumerator;
try
{
enumerator = collection.GetEnumerator();
for (var i = 0; enumerator.MoveNext() && (i < maxListLength || maxListLength == -1); i++)
{
if (enumerator.Current == null) continue;
WriteComplexObject(enumerator.Current.GetType().Name, enumerator.Current, writer, recurringObjects, depth + 1, maxDepth, maxListLength);
}
}
catch (Exception ex)
{
writer.WriteElementString(ex.GetType().Name, ReadExceptionMessage(ex));
}
finally
{
var disposable = enumerator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
writer.WriteEndElement();
}
}
我仍然有兴趣知道是否有更多久经考验的解决方案。
关于C#:将对象呈现为 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/578729/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我是HanamiWorld的新人。我已经写了这段代码:moduleWeb::Views::HomeclassIndexincludeWeb::ViewincludeHanami::Helpers::HtmlHelperdeftitlehtml.headerdoh1'Testsearchengine',id:'title'hrdiv(id:'test')dolink_to('Home',"/",class:'mnu_orizontal')link_to('About',"/",class:'mnu_orizontal')endendendendend我在模板上调用了title方法。htm
我正在构建一个应用程序,想知道是否将未使用的对象设置为nil是生产级编码中的常见做法。我知道这只是垃圾收集器的提示,并不总是处理对象。 最佳答案 根据这个thread如果您使用完一个成员对象,将其设置为nil将引发被引用对象被垃圾回收。如果它是局部变量,方法exit将做同样的事情。也就是说,如果您要求将成员显式设置为nil,我会质疑您的设计。 关于ruby-将对象设置为nil是否很常见?,我们在StackOverflow上找到一个类似的问题: https://
我有以下现有的Dog对象数组,它们按age属性排序:classDogattr_accessor:agedefinitialize(age)@age=ageendenddogs=[Dog.new(1),Dog.new(4),Dog.new(10)]我现在想插入一条新的狗记录,并将它放在数组中的正确位置。假设我想插入这个对象:another_dog=Dog.new(8)我想把它插入到数组中,让它成为数组中的第三项。这是一个人为的示例,旨在演示我特别想如何将一个项目插入到现有的有序数组中。我意识到我可以创建一个全新的数组并重新对所有对象进行排序,但这不是我的目标。谢谢!
我想禁用HTTP参数的自动XML解析。但我发现命令仅适用于Rails2.x,它们都不适用于3.0:config.action_controller.param_parsers.deleteMime::XML(application.rb)ActionController::Base.param_parsers.deleteMime::XMLRails3.0中的等价物是什么? 最佳答案 根据CVE-2013-0156的最新安全公告你可以将它用于Rails3.0。3.1和3.2ActionDispatch::ParamsParser::
我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume
我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用