WCF类型冲突

时间:2009-03-21 22:21:35

标签: c# wcf

我遇到了WCF问题。我想我明白这个问题是什么,但我需要 测试这种理解,并询问是否有人之前已经看过这个或可以建议 变通方法或替代方法。请耐心等待:这是一个相当大的 问题很难分解为最小的测试用例。

问题:我正在为旧邮件系统编写C#接口。我有 为直接接口实现了互操作程序集,并且一切正常。该 它的基础是我有一个每个消息类型的类和一个泛型类 为了传递,它只占用与最大尺寸信息相同的空间。

每个消息类都实现强制转换操作符以强制转换为此转换 泛型类,称为QOD_Message。泛型类和单个消息 类都是从无体的最小消息类派生而来的。客户端C#app 想要发送消息只是在接口程序集中调用send方法 采用QOD_Message,转换为通用类型进行发送。接收器事件 传递接收C#app一个泛型类型,根据常见类型转换 与消息类型具有一对一关系的成员。

我已经实现了本地直接接口程序集,这一切都运行正常 现在我可以在C#测试应用程序和现有的原生传统之间发送消息 应用。精彩。基本类结构如下所示:

public class QOD_Message_Minimal
{
   a message header
}

public class QOD_Message : QOD_Message_Minimal
{
   generic message - defines an empty body
}

public class QOD_WcfDialout : QOD_Message_Minimal
{
   ... some irrelevant code

   // cast operators to convert to and from the abstract message class.

   public static implicit operator QOD_Message (QOD_WcfDialout m)
   {
      ... some irrelevant code
   }

   public static implicit operator QOD_WcfDialout (QOD_Message m)
   {
      ... some irrelevant code
   }
}

注意演员操作符。

现在出现了问题。我想扩展这个接口以支持WCF,所以 另一组海外开发人员可以通过WCF与适配器进行通信 我写的WCF服务。这被称为,令人钦佩的缺乏 想象力,WCF_Adapter。 WCF_Adapter公开用于测试目的a 采用字符串的单个方法(拨号),并将其转换为消息 遗留代码。这也很好,通过调用我的函数 WCF_Client应用程序被转换为遗留消息并发送给 (固定)收件人。

所以我尝试扩展接口以添加一个接受a的入口点 QOD_Message(Dispatch),希望这与直接工作方式相同 接口,即发送方将其消息转换为QOD_Message,调用 具有此类型的发送函数,并且适配器将简单地传递 收到通用消息到其本地接口程序集中继续 调度。因此,WCF代码看起来与普通消息传递完全一样 代码。

[ServiceContract]
public interface IDialout
{
   [OperationContract (IsOneWay = true)]
   void Dialout (string NumberToDial);

   [OperationContract (IsOneWay = true)]
   void Dispatch (QOD_Message msg);
}

所以我扩展了客户端和WCF_adapter服务,生成 我的WCF客户端的代理代码和....哦。客户端无法编译。

似乎客户端应用程序无法理解强制转换操作符,并抛出一个 编译错误。即使我将消息传递程序集包含在上面的代码中 作为参考,客户端代码“更喜欢”生成中定义的类型 代理并忽略原始消息类型,因此它无法“看到”强制转换和 不会编译。这是错误:

警告CS0436: 'blah-blah \ generatedProxy.cs'中的'QOD_Messaging.QOD_Message'类型 与导入的类型'QOD_Messaging.QOD_Message'冲突 “夸夸其谈\ QOD_Messaging.dll”。使用'blah-blah \ generatedProxy.cs'中定义的类型。

据我所知,生成的代理中定义的类是正确的, 但是,生成的代理类当然只定义数据成员,而不是功能。 它包含两个类

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="QOD_Message_Minimal", Namespace="http://schemas.datacontract.org/2004/07/QOD_Messaging")]
[System.Runtime.Serialization.KnownTypeAttribute(typeof(QOD_Messaging.QOD_Message))]
public partial class QOD_Message_Minimal : object, System.Runtime.Serialization.IExtensibleDataObject
{
   whole slew of data members.
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="QOD_Message", Namespace="http://schemas.datacontract.org/2004/07/QOD_Messaging")]
public partial class QOD_Message : QOD_Messaging.QOD_Message_Minimal
{
   extra stuff to define the added body.
}

所以.....

我可以退出程序集引用,因此代码无法看到转换并失败 编译,或者我可以保留引用,编译器故意忽略 程序集的类型定义并使用代理定义...并且无法编译。

让其他WCF开发人员以前见过这种事吗?或者每个人都坚持 调用WCF端点时的简单值参数?我只是不得不这样做 为每种消息I声明一个具有唯一类参数的端点 可能想发送?这是一场维护噩梦。

2 个答案:

答案 0 :(得分:1)

转换运算符不是生成的mex的一部分,因此它们不会存在于客户端。

鉴于此处的复杂性 - 是否可以使用汇编共享?即,而不是生成(代理)类型,您可以引用类型的原始程序集?这在IDE中都受支持(在“高级”对话框中,虽然默认情况下似乎已启用,因此如果您具有对具有消息类型的程序集的引用,则可能已经工作)和通过svcutil(/ r开关)。然后,您可以在客户端获得原始类型,转换。

如果您想保留代理方法,可以为每条消息添加部分类,并在那里添加额外的转换 - 但这会产生明显的维护成本。

答案 1 :(得分:1)

可以在Web服务中公开的唯一类成员是一种方法。可以公开属性,运算符,强制转换,索引器,委托,事件或其他任何内容。

回想一下,一种方式或一种方式,Web服务由一个或多个XML文档描述:WSDL,XML Schema,WS-Policy等。这些文档都没有一种方法可以描述任何类型的编程语言运算符,包括演员。

可以将类方法公开为Web服务操作符,并且可以将类公开为数据契约或错误契约,将其公开为XML模式,并将消息契约公开为消息类型。没有别的东西可以曝光。