【问题标题】:WCF - Passing objects that are not declared as a ServiceKnownTypeWCF - 传递未声明为 ServiceKnownType 的对象
【发布时间】:2011-06-01 10:01:29
【问题描述】:

我有以下通过 net.tcp 公开的 WCF 接口:

[ServiceContract]
public interface IMyWCFService
{
    [OperationContract]
    Response ProcessRequest(Request request);
}

这是由以下类驱动的(为本问题的目的已大大简化):

[Serializable]
public abstract class Message
{
    [XmlAttribute]
    public string Sender { get; set; }
    [XmlAttribute]
    public string Recevier { get; set; }
}

[Serializable]
public abstract class Response : Message
{
    [XmlAttribute]
    public int EventCode { get; set; }
}

[Serializable]
public abstract class Request : Message
{
    [XmlAttribute]
    public string SourceSystem { get; set; }
}

[XmlRoot(Namespace="http://blah.blah.com/blah/")]
public class StringRequest : Request
{
    [XmlElement]
    public string Payload { get; set; }
}

[XmlRoot(Namespace="http://blah.blah.com/blah/")]
public class StringResponse : Response
{
    [XmlElement]
    public string Payload { get; set; }
}

注意:我们使用 XMLSerializer 而不是 DataContractSerializer,因为这些类必须与基于 .NET 2 的旧系统兼容。

由于接口在 ProcessRequest 方法中使用了抽象的 Request/Response 类,我们必须将 StringResponse / StringRequest 声明为ServiceKnownType,例如:

[ServiceContract]
[ServiceKnownType(typeof(StringRequest))]
[ServiceKnownType(typeof(StringResponse))]
public interface IMyWCFService
{
    [OperationContract]
    ResponseMessage ProcessRequest(RequestMessage request);
}

这很好用,世界上一切都很好,但是.....

WCF 侦听器只是更大框架的一个组件,上面描述的类贯穿始终。我们还设计了框架以允许我们相对轻松地添加新类型的请求/响应消息。例如,我可能会添加:

public class CustomRequest : Request
{
    public MyCustomXmlSerialisableRequestObject Payload { get; set; }
}

public class CustomResponse: Response
{
    public MyCustomXmlSerialisableResponseObject Payload { get; set; }
}

在我获得 WCF 服务接口之前,这也可以正常工作。当我们添加一个新的自定义请求/响应对时,我们还需要更新接口上的 ServiceKnownType 以包含它们。这意味着我必须重新部署服务。所以问题是 - 有什么办法可以避免更新界面?

作为一个例子,当我们使用远程处理时,我们可以传递我们喜欢的任何对象,只要它们是可序列化的,所以我假设/希望 WCF 中有类似的解决方案。

编辑:更新

遵循此处的指南:

http://ashgeek.blogspot.com/2011/02/wcf-serialization-dynamically-add.html

我似乎在正确的轨道上。但是,当我更新客户端服务引用时,它会将所有动态类型拉入服务引用中。这是不可取的,因为并非所有客户端都需要或应该知道从请求/响应派生的所有消息

更重要的是我似乎丢失了用于推送消息的 ServiceClient 类,例如:

// Client proxy class goes AWOL after service reference update
var client = new MyServiceReference.Client();
var responseMessage = client.ProcessRequest(requestMessage)

【问题讨论】:

    标签: c# wcf datacontractserializer xmlserializer


    【解决方案1】:

    一开始您提到您需要与 .NET 2.0 服务兼容,但同时您抱怨在 .NET 远程处理中工作的东西在 WCF 中不起作用 - 您受到 .NET 可能提供的功能的限制2.0 Web 服务,服务器和客户端都必须知道服务层上传输的类型 = 类型必须在服务描述和 WSDL 中。此外,由于您决定使用 XmlSerializer,您通常会丢失大部分实现该目标的方法:

    XmlSerializer 你有一个选择

    • 在您的服务操作中返回 XElement 并接收 XElement 并自行处理 XML - 在 .NET 2.0 中不起作用

    编辑:

    服务描述中没有动态行为。它仅在主机启动时创建一次,之后在您重新启动主机之前不会更改。如果您需要每个客户端的 WSDL 子集,则需要为每个客户端提供单独的端点,并且您必须准确定义应该在每个端点上公开哪些数据协定。

    【讨论】:

    • 虽然我意识到 .NET 2 正在削弱这里的东西,但不幸的是,与 .NET 2 的兼容性是必不可少的。请求/响应类在整个大型框架(300k 客户端,5k 服务器)中使用,其中很大一部分只是 .NET 2 - 升级它们的成本/时间/等影响是巨大的。这就是选择 XmlSerialiser 而不是 DataContract 的原因和这个问题:stackoverflow.com/questions/5957524/…。 XElement 不可行,因为这是在 3.5 中与 Linq 一起引入的,因此它不能在 .NET2 类中使用。
    • 是的,XElement 是对的——我忘了​​。在这种情况下,我想知道您为什么不使用 .NET 远程处理。
    • 其中一个核心服务有 .NET 3.5 可用,并且从上面有“新的闪亮事物”的势头来使用 WCF。所有这一切都表明 WCF 服务目前支持字符串和二进制请求/响应消息。有了这个,我们可以传递 XML/byte[] ,然后我们自己处理它。它可以工作,但最好有一个类型化的界面。但是,我似乎陷入了困境和 .NET 2 之间:)
    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 2019-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多