WCF 服务代理中伪装的类型?

Posted

技术标签:

【中文标题】WCF 服务代理中伪装的类型?【英文标题】:Types Being Camouflaged in WCF Service Proxy? 【发布时间】:2011-12-22 22:49:07 【问题描述】:

我的 Visual Studio 解决方案中有三个项目:

    “核心”包含一堆类型。 “WCF Service”在服务方法中使用“Core”中的所有类型。 “Test Client”是一个测试客户端应用,只有一堆测试 代码。

当我在我的测试客户端中使用我的 WCF 服务时,一切看起来都很好。生成服务方法的代理,因此我可以传递具有正确类型的参数,例如Core.BusinessObj。但是,当我从 Core 使用相同的 WCF 服务时,正在生成的代理需要这些相同的服务方法才能像这样传递:ServiceProxy.BusinessObj。这导致了一个问题,因为我想创建 Core.BusinessObj 类型的对象并将它们传递给我的服务,无论该服务在哪里使用。我确信这与在定义了所有类型的同一个项目中引用我的 WCF 服务有关,但无法弄清楚如何正确识别命名空间。

有谁知道我做错了什么?

【问题讨论】:

【参考方案1】:

您没有做错任何事 - 这正是 WCF 的工作方式!

在构建服务时,您需要定义这些服务所期望的服务方法和参数(及其数据类型)。这在服务器端打包,通常通过元数据交换 (MEX) 公开。

当客户端出现并为您的服务创建客户端代理时,它可以依赖的只是元数据中的点点滴滴——服务方法的描述(名称、参数),以及对服务的描述XML 看起来就像在客户端和服务器之间传输。

WCF 中的客户端和服务器通过序列化 (XML) 消息 相互通信 - 没有其他连接 - 没有直接链接或任何东西。所以客户端所能做的就是确保他基于服务元数据创建的数据类型将序列化为服务期望的相同 XML(并且他能够反序列化来自服务器)。

客户端创建新的客户端类型,它们将具有相同的“XML 足迹”(在序列化 XML 中具有相同的结构)——但这就是他所能做的。这就是为什么您会得到看起来非常相似的类型 - 但它们不同(通常在不同的命名空间中)。这也是为什么您不应该在服务器端数据合同中包含任何功能(代码)的原因——您不能通过 XML 消息序列化功能.....

现在,如果您控制通信线的两端(服务器和客户端)并且将它们都写在 .NET 中,那么您可以采取“捷径”来重用这些类型。基本上,您需要做您所做的 - 将所有类型和接口放入一个单独的程序集(“核心”)中。下一步:在客户端创建 WCF 代理之前,请确保客户端项目引用该“核心”程序集。当您创建引用了“核心”程序集的 WCF 客户端代理时,您可以告诉 WCF“在引用的程序集中重用类型” - 如果您启用了此选项(默认情况下处于启用状态),那么如果您引用的程序集已经包含一种符合 WCF 客户端需求的数据类型,然后该类型(来自您的“核心”程序集)将被重用(而不是创建一个新类型)。

WCF - 添加服务参考 - 高级选项

【讨论】:

谢谢。我想我需要重新设计我的项目。我在通过网络发送的类型中内置了逻辑。通过在构建客户端代理之前包含我的类型的程序集,我得到了我正在寻找的结果。现在我只需要重写所有内容:-)【参考方案2】:

确保您的 Core.BusinessObj 是可序列化的

(例如,假设它适用于 .NET 4)

[Serializable]
public class BusinessObj 

确保您的服务构建良好(没有错误)

更新服务引用(成功构建服务后)

【讨论】:

所有内容都已标记为可序列化 - 否则测试客户端将无法使用和使用该服务。我只是在使用 Core 项目(定义类型)中的服务时遇到问题。 与其使用[Serializable],不如使用[DataContract]【参考方案3】:

我按照您的描述构建了一个解决方案。它通过测试没有任何问题。 在我的解决方案中,现在有 3 个项目

    核心 WCFService TestClient

Project Core 有一个类“BusinessObj”

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

namespace Core

    [Serializable]
    public class BusinessObj
    
        public int id  get; set; 
    

项目 WCFService 有一个名为“Service1”的 WebService (已添加对 Core 的引用)

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

namespace WCFService

    public class Service1 : IService1
    
        public Core.BusinessObj GetBusinessObj()
        
            return new Core.BusinessObj()
            
                id = 1
            ;
        
    

测试项目,TestClient 有一个单元测试“UnitTest1” (已添加对 Core 的引用) (已添加对 Service1 的服务引用)

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestClient.ServiceReference;
using Core;

namespace TestClient

    [TestClass]
    public class UnitTest1
    
        [TestMethod]
        public void TestMethod1()
        
            Service1Client ServiceProxy = new Service1Client();

            BusinessObj x = ServiceProxy.GetBusinessObj();
            Assert.IsTrue(x.id == 1, "Something's wrong dude!!!");

        
    

我认为“使用 Core;”您的 TestClient 中缺少

【讨论】:

Romi,问题不在于 TestClient - 它运行良好。我的问题是当我尝试从 Core 中使用 WCFService 时。例如,在上面的示例中,从 BusinessObj 内部调用服务时出现问题。使用 ServiceName.BusinessObj 而不是 Core.BusinessObj 生成代理。

以上是关于WCF 服务代理中伪装的类型?的主要内容,如果未能解决你的问题,请参考以下文章

WCF 代理返回数组而不是列表,即使集合类型 == Generic.List

WCF 常见类型未重用

WCF常见类型不重用

修改NGINX版本名称伪装任意

服务引用不生成客户端类型

enginx 代理转发 wcf接口