将不相关的契约注入由WCF的MEX提供者创建的WSDL中

时间:2009-05-14 21:50:41

标签: wcf web-services wsdl metadata contract

我正在实施一个WCF服务(合同A),最终将调用客户端托管的独立服务(合同B)。在设计时,当客户端查询我的服务的WSDL以构建其代理时,我想包含合同B的WSDL,以便客户端可以围绕它构建其服务。不幸的是,我无法弄清楚如何将Contract B注入服务发出的WSDL中。由于契约是一个接口,并且没有[DataContract]属性,我无法将其添加为已知类型。有没有其他方法可以将合同注入到发出的WSDL中?

以下是一个例子:

[ServiceContract]
public interface IServerService
{
  [OperationContract]
  void GiveTheServerMyServiceUri(string uri);

  [OperationContract]
  void TellAllClientsSomething(string message);
}

// THIS IS THE INTERFACE I WANT TO INCLUDE IN THE WSDL
[ServiceContract]
public interface IClientService
{
  [OperationContract]
  void ReceiveMessageFromServer(string message);
}

public class ServerService : IServerService
{
  private List<string> knownClients;

  public void GiveTheServerMyServiceUri(string uri)
  { 
    knownClients.Add(uri);
  }

  public void TellAllClientsSomething(string message)
  {
    foreach (string clientUri in knownClients)
    {
      // 1. Create instance of ClientServiceProxy using client's uri
      // 2. Call proxy.ReceiveMessageFromServer(message)
    }
  }
}

起初,这似乎是双面合同的教科书示例。但是,对于这个特定的应用程序,由于各种原因,我需要在客户端和服务器之间进行更多的分离,所以我希望只给客户端一个实现的接口(通过WSDL),让它托管自己的服务,然后告诉我服务的网址。

1 个答案:

答案 0 :(得分:1)

我不认为这是有道理的。除非您的服务正在实施其他服务的服务合同,否则请不要这样做。

另一方面,您的服务可以实施其他服务合同,并成为其他服务的客户。然后,它可以将对其他服务合同的调用委托给该其他服务。


我只是试着确保这一点。我创建了一个新的WCF服务库项目。这创建了一个实现IService1的Service1,它有两个操作。我修改了[ServiceContract]属性以使用特定的命名空间(http://localhost/service1)。

然后我添加了一个新服务,它通过单个操作(DoWork)为我提供了Service2,实现了IService2。我更新了[ServiceContract]以使用http://localhost/service2/

然后我更新了Service1以实现IService2和IService1,并将IService2.DoWork委托给Service2服务。我还必须添加一个实现IService2的新端点,我必须指定一个相对地址,这样两者就不会冲突(因为它们在同一个项目中)。结果如下:

using System;

namespace WcfServiceLibrary1
{
    public class Service1 : IService1, IService2
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }

        public void DoWork()
        {
            Service2Reference.IService2 svc = null;
            try
            {
                svc = new Service2Reference.Service2Client();
                svc.DoWork();
            }
            finally
            {
                if (svc != null)
                {
                    ((IDisposable)svc).Dispose();
                }
            }
        }
    }
}