Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WCF与mocking_C#_Wcf_Dependency Injection_Mocking_Coupling - Fatal编程技术网

C# WCF与mocking

C# WCF与mocking,c#,wcf,dependency-injection,mocking,coupling,C#,Wcf,Dependency Injection,Mocking,Coupling,我对WCF缺乏经验,也无法找到一种无痛的方式来模拟WCF服务 情况:客户端和服务器都可以访问定义服务的接口,如: public interface ICustomerService { [OperationContract] Customer GetCustomer(int id); } 现在,我的第一个问题是,您是否有理由不想让客户端和服务器共享在共享库中定义服务的相同接口类型。当然,如果该服务的消费者不是.NET,或者如果您将其暴露给没有该库的第三方,那么这根本不可能,但如果有可能

我对WCF缺乏经验,也无法找到一种无痛的方式来模拟WCF服务

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

public interface ICustomerService
{
  [OperationContract]
  Customer GetCustomer(int id);
}
现在,我的第一个问题是,您是否有理由不想让客户端和服务器共享在共享库中定义服务的相同接口类型。当然,如果该服务的消费者不是.NET,或者如果您将其暴露给没有该库的第三方,那么这根本不可能,但如果有可能,我共享它不会影响其他场景,对吗

第二,如果这不是一个坏主意,那么我实际上如何让VisualStudio重用服务接口呢?我通过检查
重用类型
,设法让它共享
客户
类型,该类型也在共享程序集中定义,但它仍然重新生成接口

但是,不管这些问题如何,我如何让客户机变得可模仿?如果我浏览VS生成的服务引用,我会得到一个具体的类型来使用,但我不希望我的代码直接引用该类型,我希望与接口对话。如果我将生成的客户端公开为
iccustomerservice
,这是可行的,那么我没有
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; }
    }
}
但这创造了一个虚假的类和接口,这不是一场灾难,但也不是很漂亮


在我走这两条路线之前,有什么明显的地方我忽略了吗

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

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

container.Register(Component
  .For<ICustomerService>()
  .ActAs(DefaultClientModel
  .On(WcfEndpoint.FromConfiguration("CustomerService")))
  .LifeStyle.Transient);
container=new WindsorContainer().AddFacility();
容器寄存器(组件
.对于()
.ActAs(默认客户端模型)
.On(WcfEndpoint.FromConfiguration(“CustomerService”))
(生活方式,短暂),;

否,在单个程序集中共享接口不会影响非托管客户端的潜在客户。别担心


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

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

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

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


如果您没有在客户端和服务器之间共享协定程序集的选项,那么下一个最好的方法就是利用部分生成的类来添加接口和关闭方法。

您尝试过Ninject.Extension.Wcf吗?这里有一个如何注入WCF服务的示例,它还显示了如何关闭它们


是的,但问题是
ICCustomerService
没有定义
Close
方法,我不想在上定义它,因为它的服务器实现不需要
Close
方法。顺便说一句,我在国际奥委会使用Ninject。你不需要,温莎将通过WCF为你处理。它知道它实现了IDisPosable从我听说的大多数事情来看,通常不建议
处置
WCF客户端,因为在
处置
(关闭连接)过程中发生的任何错误都将被隐藏。@Julian-windsor WCF专门用于创建和注入服务客户端或主机。现在我甚至不知道你是否在使用Windsor,所以这些都不相关。谢谢,但是有没有更简单的方法来编写一个既有服务的
ICCustomerService
方法,又有客户端需要运行的功能(例如
Close
方法)的客户端?
IServiceClient
示例是我能想到的最优雅的示例。下面是一个非常类似的问题:
container = new WindsorContainer().AddFacility<WcfFacility>();

container.Register(Component
  .For<ICustomerService>()
  .ActAs(DefaultClientModel
  .On(WcfEndpoint.FromConfiguration("CustomerService")))
  .LifeStyle.Transient);