代码改变世界

WCF DataContract EmitDefaultValue

2011-11-29 11:41  无名365  阅读(742)  评论(0编辑  收藏  举报
The WCF DataContract model is ‘opt-in’; to include a member in the contract, explicitly apply the DataMemberAttribute to the field or property to include it in the serialized output. What if I want some properties to ‘opt-out’ under certain scenarios, should I be able to do this at runtime?

One possible solution is the use of the Data Member Default Values (http://msdn.microsoft.com/en-us/library/aa347792.aspx) . In .NET, all types have the concept of a default value and uninitialised, these are the initial states of the types.

The System.Runtime.Serialization.DataMemberAttribute has a property EmitDefaultValue. By default it is true which is why you may see entries in the service response like

<sig i:nil="true" >

Set DataMemberAttribute = false, and when a property is in its ‘default’ state, it wont be included in the serialization.

For example a DataContract may be described by

[DataContract]
public class DataResponse
{
public DataResponse()
{
version = "0.6";
reqId = "0";
status = "ok";

}

[DataMember(EmitDefaultValue=false) ]
public String version { get; set; }

[DataMember(EmitDefaultValue = false)]
public String reqId { get; set; }

[DataMember(EmitDefaultValue = false)]
public String status { get; set; }

[DataMember(EmitDefaultValue = false)]
public String warnings { get; set; }

[DataMember(EmitDefaultValue = false)]
public String errors{get;set;}

[DataMember(EmitDefaultValue = false)]
public String sig { get; set; }

[DataMember(EmitDefaultValue = false)]
public String table { get; set; }
}

With some properties initialised on creation, others to be completed at runtime.

If I only want to serialize the errors property when the status is equal to “errors” then EmitDefaultValue = false excludes the errors property until it is explicity set.
if (this.item.status == "errors")
{
this.item.errors = "...some error information structure...";
}

Whereupon the errors property will be included in the serialization.

Likewise by setting the property back to the default value

this.item.errors = null;

excludes it again.

This is a fairly simplistic approach to controlling the serialized structure, however it is the least intrusive without getting into Reflection and the bowels of the serialization process.