简体   繁体   English

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

[英]Serializing Object Tree for WCF transfer in Silverlight using IsReference=true

I'm using Silverlight 4, .NET 4.0. 我正在使用Silverlight 4,.NET 4.0。

I have an object that's defined in a shared library (shared between my Silverlight project, and the web project hosting the WCF service) 我有一个在共享库中定义的对象(在我的Silverlight项目和托管WCF服务的Web项目之间共享)

The object is a tree structure which has a list of its children, as well as reference to its parent and to the root. 该对象是一个树结构,具有其子级列表以及对其父级和根的引用。

ie. 即。

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

The problem is when Silverlight tries to take this object and send it to the server, I get an exception about cyclical references. 问题是,当Silverlight尝试获取此对象并将其发送到服务器时,出现有关循环引用的异常。 After some research, I found out I had to enable the attribute IsReference to true like so: 经过研究,我发现必须像这样将属性IsReference设置为true:

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

The problem is when I do this, my WCF service no longer works as it can't load the needed assembly for this: 问题是当我这样做时,我的WCF服务不再起作用,因为它无法为此加载所需的程序集:

"Could not load file or assembly 'System.Runtime.Serialization, Version=2.0.5.0" “无法加载文件或程序集'System.Runtime.Serialization,版本= 2.0.5.0”

This is because the project containing the TreeNode class is built against the Silverlight runtime, not the .NET runtime and uses System.Runtime.Serialization v2.0.5.0, while the web project and the WCF service uses v4.0.30319. 这是因为包含TreeNode类的项目是针对Silverlight运行时而不是.NET运行时构建的,并且使用System.Runtime.Serialization v2.0.5.0,而Web项目和WCF服务使用v4.0.30319。

So, my question is: Is there a way that I can have this object serialize while preserving references without moving the entire object structure a different project that builds against the standard .NET 4.0 runtime? 因此,我的问题是:有没有一种方法可以使该对象序列化,同时保留引用,而不必将整个对象结构移到针对标准.NET 4.0运行时构建的其他项目中?

Also, it's worth noting that I've tried using conditional compilation such as: 另外,值得注意的是,我尝试使用条件编译,例如:

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

But that doesn't work, as it's the WCF service that needs to know it must preserve references... 但这不起作用,因为需要知道它是WCF服务必须保留引用...

Greatly appreciate any help on this. 非常感谢任何帮助。

There are three options I've used for this scenario: 在这种情况下,我使用了三个选项:

  1. Proxies 代理
  2. Not sharing the assembly, but rather sharing the code. 不共享程序集,而是共享代码。
  3. Referencing the System.Runtime.Serialization for SL from the full .NET code and setting copy local to true (and optionally using an ILMerge post build step to merge in the System.Runtime.Serialization assembly and internalize it to prevent other assemblies from using it). 从完整的.NET代码引用SL的System.Runtime.Serialization,并将本地副本设置为true(并且可以选择使用ILMerge生成后步骤合并到System.Runtime.Serialization程序集中并对其进行内部化,以防止其他程序集使用它)。

2 is the most straightforward. 2是最直接的。 Keep the DataContract with IsReference = true. 保持DataContract为IsReference = true。 Create another project targeted to .NET (the other one targeted to SL). 创建另一个针对.NET的项目(另一个针对SL的项目)。 In the .NET project add your files as linked files. 在.NET项目中,将文件添加为链接文件。 That way, when it compiles, the SL one will use the System.Runtime.Serialization dll for SL and the .NET project will use the System.Runtime.Serialization dll for .NET. 这样,SL编译时,SL将使用System.Runtime.Serialization dll用于SL,而.NET项目将使用System.Runtime.Serialization dll用于.NET。

1 and 3 allow you to keep sharing the actual DLL. 1和3允许您继续共享实际的DLL。

Option 1 works as follows: Remove the DataContract attribute. 选项1的工作方式如下:删除DataContract属性。 Before serializing over the wire, create proxy types dynamically that match your classes that you want to serialize (but add the DataContract attribute with IsReference = true). 在通过网络进行序列化之前,请动态创建与要序列化的类相匹配的代理类型(但要使用IsReference = true添加DataContract属性)。 You can create these classes using Reflection.Emit (or some other dynamic type builder like Windsor). 您可以使用Reflection.Emit(或其他一些动态类型生成器,如Windsor)创建这些类。 Then use something like AutoMapper to copy your data into the proxy types. 然后使用诸如AutoMapper之类的东西将数据复制到代理类型中。 Serialize/Deserialize the proxied types. 序列化/反序列化代理类型。

Option 3 works like this: Leave your code like you have it now (with the DataContract and IsReference = true). 选项3的工作方式如下:让您的代码保持现在的状态(使用DataContract和IsReference = true)。 Set System.Runtime.Serialization to Copy Local. 将System.Runtime.Serialization设置为Copy Local。 Optionally add an ILMerge post build task with the /internalize option to merge the System.Runtime.Serialization dll into your own. (可选)使用/ internalize选项添加ILMerge生成后任务,以将System.Runtime.Serialization dll合并到您自己的文件中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM