Programming WCF Services翻译笔记(四)

本书的第2节要教学了劳动契约。内容:“本章首先会见谈谈哪些通过操作重载与契约层级,为少种植截然不同不同之编程模型建立涉。然后,本章会介绍部分略而还要有力的规划和分手服务契约的技艺以及指导规范。在本章末尾,还以身作则了什么通过编程方式以运转时落实同契约元数据的互动。”

操作重载

C++与C#备支持操作的重载,但以WCF的编程模型中,却并无支持这种技术。坦白说,在WCF的编程模型,对于面向对象的支撑且是比弱的,包括后要介绍的延续体系及多态,都有很多题材。因此,在劳务端我们不克定义这样的劳务契约:
[ServiceContract]
interface ICalculator
{
   [OperationContract]
   int Add(int arg1,int arg2);

   [OperationContract]
   double Add(double arg1,double arg2);
}

虽然于编译时会由此,然而如果以装载宿主时,就会见丢来InvalidOperationException异常。以ICalculator契约为条例,WCF会认为是零个操作。

缓解的章程是以OperationContract特性的Name属性,例如:
[ServiceContract]
interface ICalculator
{
   [OperationContract(Name = “AddInt”)]
   int Add(int arg1,int arg2);

   [OperationContract(Name = “AddDouble”)]
   double Add(double arg1,double arg2);
}

然用这种办法,存在的题材是别的代理会将Name属性指定的称作为代理操作的法名。这对编程者而言,并非好之艺术。所幸我们好手动对转移的代办进行改动,将其修改也跟服务契约一致的操作名。由于,此时经Name指定了操作的号,因此,避免了装载宿主抛来的良。

契约的继承

就是父接口标记了[ServiceContract],子接口仍然需要标记[ServiceContract],因为ServiceContractAttribute是不行延续的。服务类对劳动契约的兑现,与民俗的C#编程没有呀界别。例如:
[ServiceContract]
interface ISimpleCalculator
{
   [OperationContract]
   int Add(int arg1,int arg2);
}
[ServiceContract]
interface IScientificCalculator : ISimpleCalculator
{
   [OperationContract]
   int Multiply(int arg1,int arg2);
}
class MyCalculator : IScientificCalculator
{
   public int Add(int arg1,int arg2)
   {
      return arg1 + arg2;
   }
   public int Multiply(int arg1,int arg2)
   {
      return arg1 * arg2;
   }
}

当众终结点的早晚,可以对极度底部的契约接口公开一个单独的终结点:
<service name=”MyCalculator”>
   <endpoint>
       <address=”http://localhost:8001/MyCalculator/”&gt;
       <binding=”basicHttpBinding”>
       <contract=” IScientificCalculator”>
   </endpoint>
</service>

客户端在导入如达到的劳动契约时,会吊销服务契约的延续层级,并使OperationContract特性中的Action与ReplyAction属性,保留原来定义每个操作的契约名。但为了要客户端编程能够同劳务编程保持一致,最好是恢复客户端的契约层级。方法并凭什么最玄妙的地方,无非就是是依据劳动契约层级对客户端契约进行手工修改。修改后底客户端契约及其代理的定义如下:
[ServiceContract]
public interface ISimpleCalculator
{
   [OperationContract]
   int Add(int arg1,int arg2);
}
public partial class SimpleCalculatorClient :
ClientBase<ISimpleCalculator>,
                                              ISimpleCalculator
{
   public int Add(int arg1,int arg2)
   {
      return Channel.Add(arg1,arg2);
   }
   //Rest of the proxy
}

[ServiceContract]
public interface IScientificCalculator : ISimpleCalculator
{
   [OperationContract]
   int Multiply(int arg1,int arg2);
}
public partial class ScientificCalculatorClient :
                          
ClientBase<IScientificCalculator>,IScientificCalculator
{
   public int Add(int arg1,int arg2)
   {
      return Channel.Add(arg1,arg2);
   }
   public int Multiply(int arg1,int arg2)
   {
      return Channel.Multiply(arg1,arg2);
   }
   //Rest of the proxy
}

作者在书中还提出了所谓的代理链(Proxy
Chaining)技术,实质上就是叫个别实现不同层级接口的代理类形成一个IS-A的接轨关系。如齐之定义,就足以使ScientificCalculatorClient继承自SimpleCalculatorClient,而无是继承ClientBase<IScientificCalculator>:
public partial class SimpleCalculatorClient :
ClientBase<IScientificCalculator>,
                                              ISimpleCalculator
{
   public int Add(int arg1,int arg2)
   {
      return Channel.Add(arg1,arg2);
   }
   //Rest of the proxy
}

public partial class ScientificCalculatorClient :
SimpleCalculatorClient,
                                                 
IScientificCalculator
{
   public int Multiply(int arg1,int arg2)
   {
      return Channel.Multiply(arg1,arg2);
   }
   //Rest of the proxy
}

除非这么,如下代码才是毋庸置疑的:
SimpleCalculatorClient proxy1 = new SimpleCalculatorClient(  );
SimpleCalculatorClient proxy2 = new ScientificCalculatorClient(  );
ScientificCalculatorClient proxy3 = new ScientificCalculatorClient(  );

**服务契约的解说和计划

**契约分离与接口隔离原则(ISP,Interface Segregation
Principle)的主导精神是如出一辙的。ISP原则建议利用多独特别的接口,而未是运用单个接口,这样可防接口污染,有利于接口重用。契约分解同如此,但它还要被实现契约代价的约。

开被提供了劳务契约的分解准则。“合理之契约分解可以兑现深特化、松散耦合、精细调整以及契约的选用。这些优势推动改进通体系。总的来说,契约分解的目的就是是要契约包含的操作尽可能少。”

规划面向服务的系统不时,需要平衡两个影响系的要素(参见图2-1)。一个凡实现服务契约的代价,一个则是将劳动契约合并或者集成为一个强内聚应用程序的代价。
 图片 1
希冀2-1  平衡服务之个数和范围

概念服务契约时,还要注意到开中所谓的准属性操作(Property-Like
Operation)的施用。一言以蔽之,就是只要波及到对目标状态的管住(在C#被貌似体现为性),则如此的操作不当吃公开为劳动操作。原因在于:“客户端应该只是承担调用操作,而出于劳动去管理服务目标的状态。”

契约查询

若是查询契约,首先用了解元数据的消息,WCF提供了如下的几只辅助类,位于System.ServiceModel.Description命名空间:
public enum MetadataExchangeClientMode
{
   MetadataExchange,
   HttpGet
}
class MetadataSet : …
{…}
public class ServiceEndpointCollection :
Collection<ServiceEndpoint>
{…}

public class MetadataExchangeClient
{
   public MetadataExchangeClient(  );
   public MetadataExchangeClient(Binding mexBinding);
   public MetadataExchangeClient(Uri address, MetadataExchangeClientMode
mode);

   public MetadataSet GetMetadata();
   public MetadataSet GetMetadata(EndpointAddress address);
   public MetadataSet GetMetadata(Uri address,MetadataExchangeClientMode
mode);
   //More members
}

public abstract class MetadataImporter
{
   public abstract ServiceEndpointCollection ImportAllEndpoints(  );
   //More members
}
public class WsdlImporter : MetadataImporter
{
   public WsdlImporter(MetadataSet metadata);
   //More members
}
public class ServiceEndpoint
{
   public EndpointAddress Address
   {get;set;}
   public Binding Binding
   {get;set;}
   public ContractDescription Contract
   {get;}
   //More members
}
public class ContractDescription
{
   public string Name
   {get;set;}
   public string Namespace
   {get;set;}
   //More members
}

写被提供了元数据的询问艺术,同时还落实了一个专程用来操作元数据的MetadataHelper类。
public static class MetadataHelper
{
   public static bool QueryContract(string mexAddress,Type
contractType);
   public static bool QueryContract(string mexAddress,string
contractNamespace, string contractName);
   //More members
}

可为MetadataHelper类提供我们想查询的契约类型,或者提供该契约的名称以及命名空间:

string address = “…”;
bool contractSupported =
MetadataHelper.QueryContract(address,typeof(IMyContract));

切切实实的落实好参见书中之叙说,完整的贯彻代码可以交作者的网站(http://www.idesign.net)去下载。