2009-10-08 66 views
1

我很难找到有关如何优雅序列化ActiveRecord对象的信息。C#Castle ActiveRecord:如何优雅地(XML)序列化ActiveRecord对象?

我们希望使用XML作为格式,因为我们需要输出我们的对象,让另一个程序能够切实地解析它们。

XML-序列化通常非常容易和直接实现,但是当尝试序列化从ActiveRecord数据库返回的对象时会出现问题。数据库返回对象的代理类,其类型不能通过[XmlInclude]属性明确预期。

例如:

public class Foo : ActiveRecordLinqBase<Foo> 
{ 
    public virtual string Bar{get;set;} 

    public virtual int FooId{get;set;} 

    public Foo(string bar) 
    { 
     Bar = bar; 
    } 

    public static void FooSerializeExample() 
    { 
     Foo tehFoozor = new Foo("omgFoo!"); 
     tehFoozor.SaveAndFlush(); 
     int id = tehFoozor.FooId; 

     //... 
     //Assume new ActiveRecord session. 

     XmlSerializer serializer = new XmlSerializer(typeof(Foo)); 

     Foo tehFoozorToSerialize = Foo.Find(id); 

     using(Stream stream = File.OpenWrite("tehFoozor.xml")) 
     { 
     serializer.Serialize(stream, tehFoozorToSerialize); //Will fail 
     } 
    } 
} 

当序列化在这里,我们会得到一个消息:
“的类型是没有预料FooProxy2e2de24df9be42909d13a67fdb00b981使用XmlInclude或SoapInclude属性来指定不是静态已知类型。 “

代理类型将完全不可预知(至少据我所知)。

作为一种临时解决方案,我的团队已将每个AR对象的属性截断为接口。然后,我们为每个实现了“容器”对象,这些对象基本上是对象的Xml-Serializable非AR版本。考虑到我们目前有18个不同的AR对象序列化,这是我们解决方案中的36个附加文件!某些东西(所有东西)告诉我这是一个糟糕的解决方案,但是我一直无法找到更好的方法。我们也尝试过使用Soap Formatter,但由于ActiveRecrodLinqBase <>没有被标记为可序列化,所以这也是一个死路一条。

+0

经过更多搜索,我发现这是发生的原因是因为我们使用“延迟加载”。这不是我们可以妥协的事情,因为我们要加载的对象将具有深层次结构,有时包含数千个要通过Microsoft MVC加载和显示的部分。 其中一位高级开发人员排队等待反思,将其作为可能的解决方案。有没有其他人通过这个? – Anj 2009-10-08 17:56:17

回答

3

获取您急切需要的所有内容,然后使用AutoMapper将其映射到DTO并序列化这些DTO。

你得到的代理错误表明你的DTO实际上使用NHibernate的代理集合,当他们应该使用普通的List<T>或数组。确保你使用ToList()或类似的。

此外,您不需要使用接口来映射DTO。

+0

我同意..永远不要尝试通过电线发送实际的物体。 Ayende写了一次,我同意他:http://ayende.com/Blog/archive/2009/05/14/the-stripper-pattern.aspx – Tigraine 2009-10-09 09:00:42

+0

我可能会被误认为,但我相信这是我们'已经在做:映射(不使用AutoMapper,因为它没有简化映射过程在这种情况下)对象的基本克隆的对象,然后序列化它们。正如我之前提到的,这增加了36个文件到我们的解决方案,并且不包括单元测试文件。 @Tigraine:我们不是通过电线发送实际的物体,但是当我们获得通过电线发送的数据时,我们需要加载每个物体的一部分。这就是为什么我们需要延迟加载。 – Anj 2009-10-09 13:57:38

+0

你说得对,你已经在使用DTO,但似乎DTO映射并不完全正确。看到我更新的答案。 – 2009-10-09 14:06:45

0

试试DataContractSerializer。

与[XmlInclude]等价的是[KnownType],其中包含一个版本,该版本可以动态提供该类型以包含首次反映该类型的类型。请参阅http://msdn.microsoft.com/en-us/library/ms730167.aspx

另外,我认为(虽然不是100%肯定).NET4.0将在DataContractSerializer中包含一个“类型映射器”功能,该功能专门使这种场景变得更容易。

如果您最终试图使用DCS并遇到问题,请发表评论以回答此问题,我会尽力回答他们。

+0

将测试以查看此解决方案是否可行,并在此处更新结果。谢谢! – Anj 2009-10-09 15:32:15