首页 文章

使用IsReference = true在Silverlight中为WCF传输序列化对象树

提问于
浏览
2

我正在使用Silverlight 4,.NET 4.0 .

我有一个在共享库中定义的对象(在我的Silverlight项目和托管WCF服务的Web项目之间共享)

该对象是一个树结构,其中包含其子项列表,以及对其父项和根的引用 .

即 .

class TreeNode
{
  public List<TreeNode> Children {get; set;}
  public TreeNode Root { get; set; }
  public TreeNode Parent { get; set; }
}

问题是当Silverlight尝试获取此对象并将其发送到服务器时,我得到一个关于循环引用的例外 . 经过一些研究,我发现我必须将属性IsReference启用为true,如下所示:

[DataContract(IsReference = true)]
class TreeNode
{
  public List<TreeNode> Children {get; set;}
  public TreeNode Root { get; set; }
  public TreeNode Parent { get; set; }
}

问题是当我这样做时,我的WCF服务不再起作用,因为它无法为此加载所需的程序集:

“无法加载文件或程序集'System.Runtime.Serialization,Version = 2.0.5.0”

这是因为包含TreeNode类的项目是针对Silverlight运行时而不是.NET运行时构建的,并且使用System.Runtime.Serialization v2.0.5.0,而Web项目和WCF服务使用v4.0.30319 .

所以,我的问题是:有没有一种方法可以让这个对象序列化,同时保留引用而不会将整个对象结构移动一个针对标准.NET 4.0运行时构建的不同项目?

另外,值得注意的是我尝试过使用条件编译,例如:

#if SILVERLIGHT
[DataContract(IsReference = true)]
#endif

但这不起作用,因为需要知道它的WCF服务必须保留引用...

非常感谢任何帮助 .

1 回答

  • 6

    我在这个场景中使用了三个选项:

    • 代理

    • 不共享程序集,而是共享代码 .

    • 从完整的.NET代码引用SL的System.Runtime.Serialization并将copy local设置为true(并且可选地使用ILMerge post构建步骤在System.Runtime.Serialization程序集中合并并将其内部化以防止其他程序集使用它) .

    2是最直截了当的 . 使用IsReference = true保持DataContract . 创建另一个针对.NET的项目(另一个针对SL的项目) . 在.NET项目中,将文件添加为链接文件 . 这样,当它编译时,SL将使用System.Runtime.Serialization dll for SL,.NET项目将使用System.Runtime.Serialization dll for .NET .

    1和3允许您继续共享实际的DLL .

    选项1的工作方式如下:删除DataContract属性 . 在对连线进行序列化之前,请动态创建与要序列化的类匹配的代理类型(但使用IsReference = true添加DataContract属性) . 您可以使用Reflection.Emit(或其他一些动态类型构建器,如Windsor)创建这些类 . 然后使用类似AutoMapper的东西将数据复制到代理类型中 . 序列化/反序列化代理类型 .

    选项3的工作方式如下:保留代码就像现在一样(使用DataContract和IsReference = true) . 将System.Runtime.Serialization设置为Copy Local . (可选)使用/ internalize选项添加ILMerge后期构建任务,以将System.Runtime.Serialization dll合并到您自己的中 .

相关问题