【问题标题】:"Copied" classes in WCF proxy codeWCF 代理代码中的“复制”类
【发布时间】:2013-02-19 02:18:24
【问题描述】:

我们正在使用 WCF 和 Visual Studio 2008 构建一个大型分布式应用程序。我们在 WCF 方面没有太多经验,因此我们正在投入一些时间来设计客户端和服务器之间的 WCF 通信原型。我们观察到,我们的服务器子系统中的 WCF 服务作为参数或返回类型引用的任何类都被 Visual Studio 通过生成的代码“复制”到客户端代理中。令我惊讶的是,在执行此操作时,Visual Studio 会更改类的命名空间。例如,假设我有以下代码:

namespace MyLibrary
{
    class MyClass
    {
        //...
    }
}

假设我将它编译成MyLibrary.dll,我的 WCF 服务对此有参考。我的一些 WCF 服务使用 MyLibrary.MyClass 作为返回类型。当我查看生成的客户端代理代码时,我发现 MyClass 自动可用(这很酷),但它不再在 MyLibrary 命名空间中,而是在 Visual Studio 生成的命名空间中。

我们计划建立一个复杂的域对象模型,其中包含分布在多个程序集中的数百个类,我担心这将如何“移植”到 Visual Studio 所做的代码生成中。此外,我担心我们设计的所有良好的命名空间层次结构可能会丢失。我们最初的愿景是为这个领域对象模型创建类库,并在服务器和客户端上部署它。但是由于 WCF 的魔法似乎可以为必要的类生成代码,我想如果我们在客户端部署自己的库会发生冲突。

那么我有两个具体问题:

  • 有没有办法让 Visual Studio 在生成客户端代理代码时使用原始命名空间方案而不是它自己的方案?如果没有,这会影响我们“复制”的库在客户端的可用性吗?
  • 我可以在客户端上部署原始库吗?我想不会,但这会导致什么样的冲突?

谢谢。

【问题讨论】:

    标签: .net wcf architecture


    【解决方案1】:

    当您添加服务引用时,您可以单击“高级”按钮,在那里您可以选中“在引用的程序集中重用类型”框。您还需要确保您拥有包含客户端项目中引用的原始类型的程序集。

    您当然可以在客户端部署原始库。

    WCF 这样做的原因 - 这个概念是服务可以由没有原始二进制文件,甚至不支持 .net(例如 Java)的客户端使用 - 因此服务边界发布所有内容客户端需要调用它并处理它的响应。

    【讨论】:

    • +1 谢谢马特。我一定会看看高级选项。
    【解决方案2】:

    根据我最近在一个非常大且旧的项目中实施 WCF 的经验,我会避免使用 Visual Studio 模板功能,如瘟疫(对于大型项目),它只会让您头疼并在未来出现幻觉问题。

    http://www.codeproject.com/Articles/114139/WCF-The-Right-Way-A-Quick-Reference-Guide

    查看那篇文章。它回答了您当前的问题,并且可能会避免很多未来的麻烦。

    除此之外,如果您的传输层有良好的实现和隔离,您绝对可以重用组件,这是不使用 VS 模板的一个重要原因。

    【讨论】:

      【解决方案3】:

      您最初的设想是完全可能的。避免 Visual Studio 生成客户端的一种方法是创建一个与服务器共享库服务接口的通用客户端,以及绑定的实现(尽管后者不是必需的,它可以使用相同的服务器/ app.config 中的客户端绑定配置,但如果最终设置相似,则很方便。

      一些客户端 c# 示例代码来理解这个想法:

              // simplified extract from a generic service client lib, 
              // needs error mgmt channel disposal etc but the concept is there
      
              // BindingFactory is our common implementation with server, 
              // bindingType is an enumeration, this could be built from 
              // configuration though or however you want
              var binding = BindingFactory.CreateBinding(bindingType);
      
              var endpointAddress = new EndpointAddress(serviceAddress,
                           EndpointIdentity.CreateSpnIdentity(string.Empty))
              var channelFactory = new ChannelFactory<IMyLibrary>(
                  binding, endpointAddress);
      
              var channel = channelFactory.CreateChannel();
      
              // IMyLibrary is the interface implemented 
              // by the service found on serviceAdress
              var result = ((IMyLibrary)channel).MyServiceFunction();
      

      【讨论】:

        猜你喜欢
        • 2011-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多