zoukankan      html  css  js  c++  java
  • 日志 20071211(WCF,实验室产品)

    摘要:今天在工作之余继续了对WCF的学习。特别是在单个Servcie暴露于多个EndPoint的情形进行了总结。

    1.由于前两天我们组发布了一个小的实验室产品,围绕实验室产品究竟应该如何发布,大家有了一点讨论,最后一位经理给出的答案比较权威,并提出了“实验室产品”和“技术类实验室产品”的区别,感觉很有启发,记录在下:
    /** 
    各位,刚才和大象交流了一下,对我们这个实验室产品的内涵有了清晰的了解。
    首先,确定咱们这个实验室产品的内容是用新的技术解决了老的业务需求,其实属于技术类实验室产品。与我们目前的实验室产品定义(用成熟技术验证不成熟业务)不同。
     所以建议单独处理。
     我们应该按照技术类实验室产品管理的办法来进行后续工作,很遗憾这个办法PMO正在制定中,预计本月完成框架。
     结合我了解的特点建议按如下办法处理:
     1、 请大象安排时间,给整个***项目组进行目前的实验室产品演示和说明(功能、性能、风险、与原有产品的关系)
     2、 请孵化组主要负责人进行评估
     3、 根据评估后的结论确定是否进行实际业务试验
     相信这个工作能给我们技术类实验室产品的管理办法增加很好的实践经验,请大象组织一下,谢谢
     而且,我个人观点,不同的产品类型实验室产品管理办法是不同的,例如单机版产品、SAAS类、ERP类等等。这点要根据客观规律区别对待。呵呵
    */

    2.DataContract是支持继承的,服务的契约中使用父类型的DataContract,但在实际的调用参数和返回值上,可以使用子类型。当然,需要在定义父类型DataContract的时候声明KnowTypeAttribute,如代码段1:
    //代码段1

    [DataContract(Namespace
    ="http://Microsoft.ServiceModel.Samples")]
    //Indicate that ComplexNumberWithMagnitude may be used in place of ComplexNumber
    [KnownType(typeof(ComplexNumberWithMagnitude))]
    public class ComplexNumber
    {
        [DataMember]
        
    private double real;
        [DataMember]
        
    private double imaginary;

        
    public ComplexNumber(double r1, double i1)
        
    {
            
    this.Real = r1;
            
    this.Imaginary = i1;
        }


        
    public double Real
        
    {
            
    get return real; }
            
    set { real = value; }
        }


        
    public double Imaginary
        
    {
            
    get return imaginary; }
            
    set { imaginary = value; }
        }

    }


    //Define the data contract for ComplexNumberWithMagnitude
    [DataContract(Namespace="http://Microsoft.ServiceModel.Samples")]
    public class ComplexNumberWithMagnitude : ComplexNumber
    {
        
    public ComplexNumberWithMagnitude(double real, double imaginary) : base(real, imaginary) { }

        [DataMember]
        
    public double Magnitude
        
    {
            
    get return Math.Sqrt(Imaginary*Imaginary  + Real*Real); }
            
    set throw new NotImplementedException(); }
        }

    }

    3.一个Service可以被暴露于多个EndPoint。而这种一对多的关系在具体应用的时候也非常灵活,比如以下几种情况:
    (1)一个Service实现了多个ServiceContract,每一个ServiceContract通过一个EndPoint来暴露。如代码段2所示:

    //代码段2

     
    // Define a service contract.
     [ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
     
    public interface ICalculator
     
    {
         
    //
     }


     
    // Define a second service contract.
     [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
     
    public interface ICalculatorSession
     
    {
         
    //
     }


     
    // Service class which implements the two contracts.
     
    // Use an InstanceContextMode of PerSession to maintain the result
     
    // An instance of the service will be bound to each session
     [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
     
    public class CalculatorService : ICalculator, ICalculatorSession
     
    {
         
    //对两个接口都进行了实现

    在这种情况下,这个服务很自然的就可以通过两个Contract来形成两个EndPoint,对外提供服务,如代码段3:

    <!--代码段 3-->

    <services>
      
    <service 
          
    name="Microsoft.ServiceModel.Samples.CalculatorService"
          behaviorConfiguration
    ="CalculatorServiceBehavior">
        
    <!-- ICalculator endpoint is exposed using BasicBinding at the base address provided by host: 
             http://localhost/servicemodelsamples/service.svc  
    -->
        
    <endpoint address=""
                  binding
    ="basicHttpBinding"
                  contract
    ="Microsoft.ServiceModel.Samples.ICalculator" />
        
    <!-- ICalculatorSession endpoint is exposed using BindingWithSession at {baseaddress}/session:
             http://localhost/servicemodelsamples/service.svc/session 
    -->
        
    <endpoint address="session"
                  binding
    ="wsHttpBinding"
                  bindingConfiguration
    ="BindingWithSession" 
                  contract
    ="Microsoft.ServiceModel.Samples.ICalculatorSession" />
      
    </service>
    </services>

    针对这两种ServiceContract,通过SvcUtil.exe生成的客户端也有两种类型,不同的客户端类型将根据自己实现的ServiceContract来选择合适的endPoint,这里就不赘言了。

    这种应用类型的总结:同一个服务的不同功能组通过Contract不同的endPoint来提供,其效果近似于提供多个服务。

    (2)一个Service只实现一个ServiceContract,但对Binding有不同的要求(如:不同的安全等级,不同的传输协议等)。在这种情况下,同一个服务也可以暴露给多个endpoint,如代码段4:

    <!--代码段4-->

    <services>
      
    <service 
          
    name="Microsoft.ServiceModel.Samples.CalculatorService"
          behaviorConfiguration
    ="CalculatorServiceBehavior">
        
    <!-- this endpoint is exposed at the base address provided by host: http://localhost/servicemodelsamples/service.svc  -->
        
    <endpoint address=""
                  binding
    ="basicHttpBinding"
                  contract
    ="Microsoft.ServiceModel.Samples.ICalculator" />
        
    <!-- secure endpoint exposed at {base address}/secure: http://localhost/servicemodelsamples/service.svc/secure -->
        
    <endpoint address="secure"
                  binding
    ="wsHttpBinding"
                  contract
    ="Microsoft.ServiceModel.Samples.ICalculator" />
      
    </service>
    </services>

    服务端提供好了,但由于这次我们只有一个ServiceContract,那么通过SvcUtil.exe生成的客户端类型也只有一个,那它是如何选择不同的endPoint的呢?注意到代码生成工具为我们提供了多个版本的客户端构造器,如代码段5:

    //代码段5

    public CalculatorClient(string endpointConfigurationName) : 
            
    base(endpointConfigurationName)
    {
    }


    public CalculatorClient(string endpointConfigurationName, string remoteAddress) : 
            
    base(endpointConfigurationName, remoteAddress)
    {
    }


    public CalculatorClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
            
    base(endpointConfigurationName, remoteAddress)
    {
    }


    public CalculatorClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
            
    base(binding, remoteAddress)
    {
    }

    所以,我们可以在客户端的App.config中声明多个endpoint,并为他们的name属性赋值,这些endpoint在binding设置上和服务器端的endpoint一一对应。我们在客户端代码中构造客户端对象的时候,把endpoint的name作为客户端对象的构造器参数即可。
      其实在这里就已经基本上解决了在 日志 20071207(CAB,Data Transfer in WCF) 上面一位兄弟提到过的问题,问题如下:
    如代码5中所示,定义了3种不同TransforMode的类型,就需要三种不同的bindingConfiguration嘛?
    这种情况下应该怎么写配置文件啊?Service的配置似乎没有细到每个方法上啊。

    换一句话说,就是某个Service的不同Operation对于binding有不同要求的时候,应该如何进行设置。呵呵,这不正是上面我们刚刚提到过的内容吗?

    这种应用类型的总结:同一个服务(所有功能或不同功能组)通过Binding不同的endPoint来提供。当不同功能组使用不同Binding设置的时候,相当于提供多个服务;否则仅仅是同一个服务通过不同绑定协议来提供。

    4.一个强大Dos命令的巧用
      需求是这样的:我有一个可执行文件a.exe,我不记得它被放在哪儿了,但它被放在系统的%path%变量里,所以我在命令行里直接键入a.exe是可以执行的。但我现在想知道a.exe究竟放在哪个目录下。由于a执行得很快,和人没有交互,所以用进程探测工具也不行。后来一个同事告诉了我一个Dos下的for命令,看了一眼帮助,貌似还真是很强大,后来试了半天,下面这个语句就能满足我的需求: for %I in (a.exe) do echo %~$PATH:I
    这里有一个链接,谈到这个命令的用法:最强之dos命令 - for


     



  • 相关阅读:
    wim文件位置
    用DISM++来管理wim当中的驱动
    交易所基金代码段
    systemd配置nginx
    MACD公式
    nginx配置
    linux的tmfps
    nohup&
    geth
    RGB
  • 原文地址:https://www.cnblogs.com/xingyukun/p/991164.html
Copyright © 2011-2022 走看看