上一章我们介绍了契约设计中的明确契约(ExplicitContract),这一章我们介绍:已知类型契约(KnownTypesContract)。
已知类型契约(KnownTypesContract)允许在服务契约中使用多态的行为;在服务操作中暴露基本类型,将已知类型(known types)相关到:基本类型(基类类型)自身、特定操作、整个服务契约;采用属性声明或者配置的方式来实现。
开发环境:Visual Studio 2010 + Net Framework 4.0 。
下面通过代码来演示已知类型契约(此项目建立在WCF面向服务应用程序系列之二:契约设计(ExplicitContract)中的解决方案中):
1、新增一个WCF Service Library程序,修改项目名称为KnownTypesContract,删除自动添加的文件。
2、新建Item.cs类,代码如下:
[DataContract(Namespace = "http://schemas.xinhaijulan.com/demos/KnownTypesContract")]
[KnownType(typeof(ItemCreate))]
//[KnownType(typeof(ItemModify))]
public class Item
{
[DataMember(Name = "IdContract", IsRequired = true, Order = 0)]
public int Id { get; set; }
[DataMember(Name = "NameContract", IsRequired = true, Order = 1)]
public string Name { get; set; }
[DataMember(Name = "MessageContract", IsRequired = true, Order = 2)]
public string Message { get; set; }
[DataMember(Name = "ItemCategoriesContract", IsRequired = true, Order = 3)]
public virtual ItemCategories ItemCategories { get; set; }
}
3、新建枚举ItemCategories.cs,代码如下:
[DataContract(Namespace = "http://schemas.xinhaijulan.com/demos/KnownTypesContract")]
public enum ItemCategories
{
[EnumMember]
None = 0,
[EnumMember]
Create = 1,
[EnumMember]
Modify = 2,
[EnumMember]
Delete = 3
}
4、新建ItemCreate.cs类,代码如下:
[DataContract(Namespace = "http://schemas.xinhaijulan.com/demos/KnownTypesContract")]
public class ItemCreate : Item
{
public ItemCreate()
{
}
[DataMember(Name = "ItemCategoriesContract", IsRequired = true, Order = 3)]
public override ItemCategories ItemCategories
{
get { return ItemCategories.Create; }
}
}
5、新建ItemModify.cs类,代码如下:
[DataContract(Namespace = "http://schemas.xinhaijulan.com/demos/KnownTypesContract")]
public class ItemModify : Item
{
public ItemModify()
{
}
[DataMember(Name = "ItemCategoriesContract", IsRequired = true, Order = 3)]
public override ItemCategories ItemCategories
{
get { return ItemCategories.Modify; }
}
}
6、新建WCF接口文件IKnownTypesService.cs,代码如下:
[ServiceContract(Name = "KnownTypesContract", Namespace = "http://schemas.xinhaijulan.com/demos/KnownTypesContract")]
public interface IKnownTypesService
{
[OperationContract(Name = "SaveItemContract")]
[ServiceKnownType(typeof(ItemCreate))]
void SaveItem(Item item);
[OperationContract(Name = "GetItemContract")]
[ServiceKnownType(typeof(ItemCreate))]
Item GetItem();
[OperationContract(Name = "SaveItemModifyContract")]
//[ServiceKnownType(typeof(ItemModify))]
void SaveItemModify(Item item);
[OperationContract(Name = "GetItemModifyContract")]
//[ServiceKnownType(typeof(ItemModify))]
Item GetItemModify();
}
注意:上述方法SaveItem和GetItem被标记了ServiceKnowType属性,而SaveItemModify和GetItemModify没有被标记为ServiceKnowType属性,只有被标记了ServiceKnowType类型的Item的继承类才能在客户端展示和被调用,否则,继承这种多态特点在客户端将不起作用。在此例中,ItemCreate将在客户端显示和被调用,ItemModify由于没有被标记为ServiceKnowType,则不可以在客户端显示和被调用。
7、创建KnownTypesService.cs类,代码如下:
public class KnownTypesService : IKnownTypesService
{
private Item _item;
public void SaveItem(Item item)
{
this._item = item;
}
public Item GetItem()
{
this._item.Message = "IExplicitService.GetItem() invoked.";
return this._item;
}
public void SaveItemModify(Item item)
{
this._item = item;
}
public Item GetItemModify()
{
this._item.Message = "IExplicitService.GetItemModify() invoked.";
return this._item;
}
}
8、修改App.config中的服务名称 、端点契约、服务地址,代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="KnownTypesContract.KnownTypesService">
<endpoint address="" binding="wsHttpBinding" contract="KnownTypesContract.IKnownTypesService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/KnownTypesContract/KnownTypesService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
9、在客户端控制台程序Client中,添加Service Reference,修改名称空间为KnownTypesService,并添加测试TestKnownTypesContract方法,代码如下:
private static void TestKnownTypesContract()
{
Console.WriteLine("-----------------Test KnownTypesContract Begin-----------------");
KnownTypesContract.KnownTypesContractClient client = new KnownTypesContract.KnownTypesContractClient();
KnownTypesContract.Item item = new KnownTypesContract.ItemCreate();
client.SaveItemContract(item);
item = client.GetItemContract();
Console.WriteLine("Get from server item.ItemCategoriesContract is : {0}", item.ItemCategoriesContract.ToString());
//item = new KnownTypesContract.ItemModify();
//client.SaveItemModifyContract(item);
//item = client.GetItemModifyContract();
//Console.WriteLine("Get from server item.ItemCategoriesContract is : {0}", item.ItemCategoriesContract.ToString());
Console.WriteLine("-----------------Test KnownTypesContract End-----------------");
}
注意:因ItemModify没有补标记为ServiceKnowType,则在客户端找不到此类,若要显示并调用此类,则需要在接口文件中添加ServiceKnowType标记。
细心的读者也许观察到Item.cs这个类中有一行注释:://[KnownType(typeof(ItemModify))],是的,这也是打开多态的开关。
总结,在已知类型契约中:1、通过基类添加KnowType标记实现多态;2、通过接口文件方法中添加ServiceKnowType标记实现多态。
至此,WCF契约设计—KnownTypesContract介绍完毕,下一章将介绍WCF契约设计(MessageContract) 。
Demo下载将在契约设计介绍全部完成时提供。请到【契约设计(MessageContract)】下载DEMO。
作者:心海巨澜
出处:http://xinhaijulan.cnblogs.com
版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。