这里有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:
每次进行更改时都必须编辑第二个文件,这与直接编辑自动生成的文件相比只是一个微小的改进。幸运的是,还有另一种更容易维护的方法。详情可查here但总而言之,您所需要做的就是装饰您的OperationContract
那是消耗Comment
具有附加属性,ReferencePreservingDataContractFormat
。请注意,该页面上提供的代码中有一个轻微错误,可能会导致无限递归。如中所述this帖子,修复非常简单:根本不用递归,只需创建一个新的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
);
}
}
就是这样!
两种方法都可以,选择适合您的方法。