1

当谈到 WCF 时,我缺乏经验,而且我真的无法找到一种无痛的方式来模拟 WCF 服务。

情况:客户端和服务器都可以访问定义服务的接口,如下所示:

public interface ICustomerService
{
  [OperationContract]
  Customer GetCustomer(int id);
}

现在,我的第一个问题是,您是否有理由不让客户端和服务器共享在共享库中定义服务的相同接口类型。当然,如果服务的使用者不是 .NET,或者如果您将其暴露给没有库的第三方,则根本不可能,但我在可能的情况下分享它不会伤害那些其他场景,对吧?

其次,如果这不是一个坏主意,我实际上如何让 Visual Studio 重用服务接口?我设法通过检查来让它共享Customer类型Re-use types,这也是在共享程序集中定义的,但它仍然重新生成接口。

但是,不管这些问题如何,我如何让客户端变得可模拟?如果我通过 VS 生成的服务引用,我会得到一个可以使用的具体类型,但我不希望我的代码直接引用该类型,我想与一个接口交谈。如果我将生成的客户端公开为ICustomerService有效的,我没有Close方法,因为接口没有定义它。

我还想到了以下方法,完全放弃了自动生成客户端,自己编写客户端,因为它很简单:

public interface IServiceClient<T>
{
    void Close();
    T Services { get; }
}

public class CustomerServiceClient : ClientBase<ICustomerService>, ICustomerService, IServiceClient<ICustomerService>
{
    public Customer GetCustomer(int id)
    {
        return base.Channel.GetCustomer(id);
    }

    public ICustomerService Services
    {
        get { return this; }
    }
}

这行得通,我可以将它作为IServiceClient<ICustomerService>我的 IoC 容器公开,但需要注意的是,现在是这样,并且当接口更改client.Services.GetCustomer(1)时,我已经失去了轻松重新生成客户端的好处。ICustomerService添加的代码很简单,但维护它可能仍然很烦人。

另一种可能性是利用生成的类是partial. 当我这样做时它也有效:

interface ICloseable
{
  void Close();
}

interface ClientInterface : ICustomerService, ICloseable
{
}

partial class CustomerServiceClient : IClientInterface
{

}

但这创建了一个虚假的类和接口,这不是灾难,但不是很漂亮。

在我走任何一条路线之前,有什么明显的我忽略的吗?

4

4 回答 4

2

你试过 Ninject.Extension.Wcf 吗?有一个如何注入 WCF 服务的示例,它还展示了如何关闭它们。

https://github.com/ninject/ninject.extensions.wcf

http://teamcity.codebetter.com/project.html?projectId=project3&tab=projectOverview

于 2010-11-03T14:00:27.487 回答
0

如果您使用 Windsor 作为您的 IoC(不确定 Unity),您可以让它注入 WCF 客户端。这意味着您的消费代码只需要担心 ICustomerService。

container = new WindsorContainer().AddFacility<WcfFacility>();

container.Register(Component
  .For<ICustomerService>()
  .ActAs(DefaultClientModel
  .On(WcfEndpoint.FromConfiguration("CustomerService")))
  .LifeStyle.Transient);
于 2010-11-01T17:52:25.113 回答
0

不,在单个程序集中共享界面不会损害非托管客户的潜在客户。别担心。

至于另一条路线——我没有使用过模拟框架,但我想知道其中一个是否有帮助。也就是说,您是否考虑过将您的测试需求从“单元测试”提升为“集成测试”?我一直在测试我的 WCF 服务的方式是让一个假客户端使用一个真正的 WCF 客户端存根,而后者又使用真正的服务器,而真正的服务器正在与一个假的服务器控制器通信。然后,我使用appdomain 魔法在一个进程中同时运行客户端和服务器进程。该单一进程在 Visual Studio 的单元测试框架的上下文中运行。所以我正在运行集成测试,就好像它们是单元测试一样。非常好!

于 2010-11-01T17:55:34.057 回答
0

自动生成客户端通常仅适用于无法在客户端和服务器之间共享代码的情况。它将为生成新类型。

共享契约(即接口和它使用的 DataContract 类型)的正确方法是在单独的程序集中定义这些类型,该程序集应分发给服务器和客户端。然后您可以在服务器上制作服务器实现,在客户端上制作客户端实现

当您拥有现成的类型时,就很容易创建自己的客户端实现,正如您自己发现的那样。这通常是我会做的。这也使得模拟和/或注入服务实现变得容易。

如果您没有选择在客户端和服务器之间共享合同程序集,那么最好的办法是利用部分生成的类来添加您的接口和 Close 方法。

于 2010-11-01T17:56:22.980 回答