这里有2个解决方案
解决方案#1:
我遇到了同样的问题,所以我用你提到的方式装饰了我的班级DataContract
和成员。DataMember
但是,我不喜欢直接编辑自动生成的代码,因为每次重新生成文件时都必须重做。为了解决这个问题,我使用了该MetadataType
属性。在你的情况下,它看起来像这样......
首先,您将保持自动生成的实体原样:
public partial class Comment
{
public int CommentId { get; set; }
public string Content { get; set; }
public System.DateTime Posted { get; set; }
public bool Approved { get; set; }
public int AnswersTo { get; set; }
public int PostId { get; set; }
public virtual Post Post { get; set; }
}
接下来,在另一个文件中,您将创建另一个部分类并像这样装饰它:
[MetadataType(typeof(Metadata))]
[DataContract(IsReference = true)]
public partial class Comment
{
private class Metadata
{
[DataMember]
public int CommentId { get; set; }
[DataMember]
public string Content { get; set; }
[DataMember]
public System.DateTime Posted { get; set; }
[DataMember]
public bool Approved { get; set; }
[DataMember]
public int AnswersTo { get; set; }
[DataMember]
public int PostId { get; set; }
[DataMember]
public virtual Post Post { get; set; } // you can remove "virtual" if you wish
}
}
MetadataType
本质上会将Metadata
好友类中的属性添加到具有相同名称的属性中Comment
(不是直接添加,但出于我们的目的,它已经足够接近了……这是另一篇文章的主题)。当然,如果您的Comment
实体发生变化,您需要相应地进行更新。
解决方案#2:
每次进行更改时都必须编辑第二个文件,这与直接编辑自动生成的文件相比略有改进。幸运的是,还有另一种更容易维护的方法。可以在此处找到详细信息,但作为总结,您需要做的就是使用附加属性来装饰OperationContract
正在消费的. 请注意,该页面上提供的代码中存在一个会导致无限递归的小错误。如本文所述,修复非常简单:根本不用递归,只需创建一个新的Comment
ReferencePreservingDataContractFormat
DataContractSerializer
这种方法的优点是,无论你改变多少Comment
,你仍然不需要更新任何东西。
作为您的代码示例,假设您使用Comment
如下:
[OperationContract]
Comment FindComment(string criteria);
您需要做的就是添加
[OperationContract]
[ReferencePreservingDataContractFormat]
Comment FindComment(string criteria);
然后在其他地方你需要定义ReferencePreservingDataContractFormat
它看起来像这样:
//From http://blogs.msdn.com/b/sowmy/archive/2006/03/26/561188.aspx and https://stackoverflow.com/questions/4266008/endless-loop-in-a-code-sample-on-serialization
public class ReferencePreservingDataContractFormatAttribute : Attribute, IOperationBehavior
{
public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
{
}
public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
{
IOperationBehavior innerBehavior = new ReferencePreservingDataContractSerializerOperationBehavior(description);
innerBehavior.ApplyClientBehavior(description, proxy);
}
public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
{
IOperationBehavior innerBehavior = new ReferencePreservingDataContractSerializerOperationBehavior(description);
innerBehavior.ApplyDispatchBehavior(description, dispatch);
}
public void Validate(OperationDescription description)
{
}
}
class ReferencePreservingDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
{
public ReferencePreservingDataContractSerializerOperationBehavior(OperationDescription operationDescription) : base(operationDescription) { }
public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes,
0x7FFF, //maxItemsInObjectGraph
false, //ignoreExtensionDataObject
true, //preserveObjectReferences
null //dataContractSurrogate
);
}
public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes,
0x7FFF, //maxItemsInObjectGraph
false, //ignoreExtensionDataObject
true, //preserveObjectReferences
null //dataContractSurrogate
);
}
}
就是这样!
任何一种方法都可以正常工作-选择适合您的方法。