0

该解决方案包括两个项目:

DemoService 项目,它是一个实现 IGetHeaders 接口的简单 WCF 服务库。此接口由一个方法 (GetHeaders) 组成,该方法检索有关发送到服务的消息中的标头的一些信息。对于本练习,它返回 Action 标头。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Channels;

namespace DemoService
{
     public class HeaderService : IGetHeaders
     {
         public string GetHeaders()
         {
             return OperationContext.Current.RequestContext.RequestMessage.Headers.Action;
         }
      }
 }

TestClient 项目,它是一个控制台应用程序,使您能够使用 DemoService 服务。已经创建了 DemoService 的代理。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestClient
{
     class Program
     {
         static void Main(string[] args)
         {
             DemoService.GetHeadersClient proxy = new DemoService.GetHeadersClient("TcpIGetHeaders");
             Console.WriteLine("And the header is: " + proxy.GetHeaders());
             Console.ReadLine();
         }
      }
 }

在对象的构造函数中,传递绑定的名称以用作唯一参数。app.config 文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
             <binding name="WsIGetHeaders" />
            </wsHttpBinding>
         <netTcpBinding>
             <binding name="TcpIGetHeaders" />
         </netTcpBinding>
        </bindings>
        <client>
              <endpoint address="http://localhost:8731/Design_Time_Addresses/DemoService/HeaderService/"
              binding="wsHttpBinding" bindingConfiguration="WsIGetHeaders"
              contract="DemoService.IGetHeaders" name="WsIGetHeaders">
              </endpoint>
              <endpoint address="net.tcp://localhost:8731/Design_Time_Addresses/DemoService/HeaderService/"
              binding="netTcpBinding" bindingConfiguration="TcpIGetHeaders"
              contract="DemoService.IGetHeaders" name="TcpIGetHeaders">
              </endpoint>
         </client>
        </system.serviceModel>
     </configuration>

我的两个问题:

  1. 在服务代码中,没有构造函数。为什么在代理对象中,我们可以传递一个唯一的参数。
  2. 为什么参数是名称必须是端点的名称,这里是="TcpIGetHeaders"。
4

1 回答 1

1

该服务确实有一个构造函数——因为没有明确定义,所以编译器提供了一个默认的无参数构造函数。以下代码行将创建服务的新实例,即使其中没​​有定义显式构造函数:

HeaderService myService = new HeaderService();

代理对象不是创建服务的实例——它是创建一个可以与服务通信的对象。添加服务引用时,.NET 会生成创建代理的代码,以及调用服务公开的方法。

如果您查看 reference.cs 文件,您将看到代理的自动生成代码。这个代理继承ClientBase<T>并实现了定义你的服务的接口。

DemoService.GetHeadersClient proxy = new DemoService.GetHeadersClient("TcpIGetHeaders");

上面的代码调用的是自动生成的GetHeadersClient类构造函数,而不是你的服务构造函数。for 的构造函数ClientBase<T>有几个重载——在上面的代码中,它使用的构造函数采用指定的端点配置(由配置文件中元素的name属性确定)。endpoint

如果您打开 referencence.cs 文件,您可能会看到与此类似的代码(使用较旧的示例,因此版本号在您的情况下可能不同,我正在对命名空间进行有根据的猜测):

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class HeaderServiceClient : System.ServiceModel.ClientBase<TestService.DemoService.IGetHeaders>, TestService.DemoService.IGetHeaders 
{

    public HeaderServiceClient() 
    {
    }

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

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

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

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

    public string GetHeadesr() 
    {
        return base.Channel.GetData(value);
    }
}

请注意具有参数的构造函数如何从ClientBase<T>.

总之,您正在调用代理的构造函数,并且您正在使用为端点配置获取字符串的重载。

有关详细信息,请参阅ClientBase(T Channel) 构造函数

于 2013-08-31T21:33:56.033 回答