1. 避免推断式数据契约(POCO)。总是显式地应用DataContract特性。
说明:推断式数据契约:如果编组类型为公共类型,且未曾标记DataContract特性,WCF就会自动推断,认为DataContract特性被应用到该类型上,且他的的所有公有成员(字段或属性)均被应用了DataMember特性。
依赖于数据契约的推断是一种草率的破解方法,它与WCF的大多数内容背道而驰。既然WCF无法从仅有的接口定义中推断出服务契约,或者默认允许事务或可靠性,它就不应该推断契约。
2. 只在属性或只读公有成员上使用Datamember特性。
说明:在属性上使用Datamember特性:
[DataContract]
public class Message
{
private stringm_sender;
private stringm_content;
private DateTimem_time;
[DataMember]
public stringSender
{
get { returnm_sender; }
set { m_sender = value; }
}
[DataMember]
public stringContent
{
get { returnm_content; }
set { m_content = value; }
}
[DataMember]
public DateTimeTime
{
get { returnm_time; }
set { m_time = value;}
}
}
在公有成员上使用DataMember:
[DataContract]
public class Contact
{
[DataMember]
public stringFirstName;
[DataMember]
public stringLastName;
}
3. 避免为定制类型显式地执行XML序列化。
说明:应该在定制类型上应用DataContract特性。
4. 避免使用消息契约。
说明:消息契约描述了要发送或接收的SOAP消息的结构。可以检查并且控制许多SOAP消息的头和消息体的细节。
利用消息契约可以让你通过提供的直接访问SOAP头和体的机制,完全控制SOAP消息的发送和接收。它允许使用简单或复杂的类型来定义SOAP中某部分的确切内容。正如当你需要完全控制数据序列化时,可以从DataContractSerializer切换为XmlSerializer一样,当你需要完全控制SOAP消息时,可以从DataContracts转变为MessageContracts。
[MessageContract]
public class StockPrice
{
[MessageHeader]
public DateTimeCurrentTime;
[MessageBodyMember]
public PriceDetails Price;
}
5. 当使用DataMemberAttribute特性的Order属性时,应该为同一类层级的所有成员分配相同的值。
说明:
[DataContract(Name="Person")]
public class Contact
{
[DataMember(Name="FirstName", Order=1)]
public stringName1;
[DataMember(Name = "LastName", Order = 1)]
public stringName2;
}
6. 数据契约应实现IExtensibleDataObject接口。使用显式接口实现。
说明:从新数据契约到旧数据契约再到新数据契约的交互方式称为版本的双向传递。WCF允许仅能识别旧契约的服务(或客户端)只传递定义在新契约的成员的状态,而不会阻止他们。其解决方案为让数据契约类型实现IExtensibleDataObject接口。
[DataContract]
public class Contact : IExtensibleDataObject
{
ExtensionDataObjectIExtensibleDataObject.ExtensionData
{ get; set;}
[DataMember]
public stringFirstName;
[DataMember]
public stringLastName;
}
7. 避免在ServiceBehavior和CallbackBehavior特性上设置IgnoreExtensionDataObject。应保持它的默认值为false。
说明:IgnoreExtensionDataObject的默认值为false。设置为true时则可以保证服务使用的所有数据契约包含的所有未知数据成员都会被忽略。
8. 不要将委托和事件标记为数据成员。
说明:下面做法是错误的:
[DataContract]
public class Contact
{
[DataMember]
public delegatevoid Test();
}
9. 不要将.NET的特殊类型例如Type作为操作的参数。
说明:服务契约的方法的参数类型不要用.net的特殊类型,如Type。
10. 不要在操作中接受或返回ADO.NET的DataSet类型和DataTable类型(或者它们的类型安全子类)。应该返回一个与技术无关的表示形式,例如数组。
说明:服务契约的方法返回值类型不要用DataSet类型和DataTable类型,应返回一个与技术无关的表示形式,如数组。
11. 禁止为泛型的类型参数生成散列值,而应该提供易懂的类型名。
说明:
下面做法是不好的:
[DataContract]
class SomeClass
{ }
[DataContract]
class MyClass<T>
{ }
[OperationContract]
void MyMethod(MyClass<SomeClass> obj);
//导出的数据契约为:
[DataContract]
class SomeClass
{ }
[DataContract]
class MyClassOfSomeClassMTRdqN6p
{ }
[OperationContract]
void MyMethod(MyClassOfSomeClassMTRdqN6p obj);