WCF返回包含流的自定义对象集合的自定义对象

WCF返回包含流的自定义对象集合的自定义对象,wcf,stream,return-value,collections,custom-object,Wcf,Stream,Return Value,Collections,Custom Object,我不知道是否可以这样做,但我有一个WCF服务,它应该返回一个自定义对象,该对象有一个包含流的另一个自定义对象的集合 当我试图返回此对象时,我得到 System.Runtime.Serialization.InvalidDataContractException:无法序列化类型“System.ServiceModel.Dispatcher.StreamFormatter+MessageBodyStream”。考虑使用DATACONTractAttor属性对其进行标记,并标记要使用DATAMEMBA

我不知道是否可以这样做,但我有一个WCF服务,它应该返回一个自定义对象,该对象有一个包含流的另一个自定义对象的集合

当我试图返回此对象时,我得到

System.Runtime.Serialization.InvalidDataContractException:无法序列化类型“System.ServiceModel.Dispatcher.StreamFormatter+MessageBodyStream”。考虑使用DATACONTractAttor属性对其进行标记,并标记要使用DATAMEMBAREATE属性序列化的所有成员。有关其他受支持的类型,请参阅Microsoft.NET Framework文档

如果我改为方法,只返回其中一个返回类型为stream的流,它就可以正常工作。这将是太多的代码,我张贴,所以我只是想在一般情况下,如果它是可能的,如果有一些特殊的事情,我要做的是让自定义对象与流返回没有错误的WCF服务

我现在在测试时使用wsHttpBindig

我已经将流和IList标记为类中的DataMembers,是否应该将它们标记为其他对象


感谢您的帮助,如果您不理解,我可以尝试创建一个小示例代码

您真的希望流式传输发生,还是只希望它序列化(并且可以对其进行缓冲)

如果您同意缓冲它:

请记住,DataContractSerializer没有内置的流支持,但它支持字节数组。因此,执行通常的DataContract类型转换技巧:不要用DataMember标记流,而是创建一个byte[]类型的私有[DataMember]属性来包装流。比如:

public Stream myStream;

[DataMember(Name="myStream")]
private byte[] myStreamWrapper {
   get { /* convert myStream to byte[] here */ }
   set { /* convert byte[] to myStream here */ }
}
如果您真的想要流式播放:

如果流是整个正文,则WCF ServiceModel只能支持流式消息正文。因此,您的操作应该返回一个MessageContract,它将所有非流内容作为头返回。像这样:

[MessageContract]
public class MyMessage {
   [MessageHeader]
   public MyDataContract someInfo;
   [MessageBody]
   public Stream myStream;
}

您是真的希望流媒体发生,还是仅仅希望它被序列化(并且可以对其进行缓冲)

如果您同意缓冲它:

请记住,DataContractSerializer没有内置的流支持,但它支持字节数组。因此,执行通常的DataContract类型转换技巧:不要用DataMember标记流,而是创建一个byte[]类型的私有[DataMember]属性来包装流。比如:

public Stream myStream;

[DataMember(Name="myStream")]
private byte[] myStreamWrapper {
   get { /* convert myStream to byte[] here */ }
   set { /* convert byte[] to myStream here */ }
}
如果您真的想要流式播放:

如果流是整个正文,则WCF ServiceModel只能支持流式消息正文。因此,您的操作应该返回一个MessageContract,它将所有非流内容作为头返回。像这样:

[MessageContract]
public class MyMessage {
   [MessageHeader]
   public MyDataContract someInfo;
   [MessageBody]
   public Stream myStream;
}

这似乎是一个重复的问题-请参阅我的答案以获得解决方案

顺便说一下

当您在[OperationContract]中直接使用流时,这是一种特殊情况。DataContractSerializer甚至没有被调用。WCF ServiceModel使用一种特殊的方式使用流写出消息体(如果底层绑定支持,则确保消息体实际上是流的)

但是,当您将流用作[DataContract]中的另一个[DataMember]时,它只是DataContractSerializer的另一种类型,而且是不受支持的类型。因此,您必须使用类型转换技巧(请参阅我前面的链接)


不直观,我知道:)但在某种程度上有记录。

这似乎是一个重复的问题-请参阅我的答案以获得解决方案

顺便说一下

当您在[OperationContract]中直接使用流时,这是一种特殊情况。DataContractSerializer甚至没有被调用。WCF ServiceModel使用一种特殊的方式使用流写出消息体(如果底层绑定支持,则确保消息体实际上是流的)

但是,当您将流用作[DataContract]中的另一个[DataMember]时,它只是DataContractSerializer的另一种类型,而且是不受支持的类型。因此,您必须使用类型转换技巧(请参阅我前面的链接)


不直观,我知道:)但在某种程度上有文档记录。

简言之:您不能将缓冲传输(发送回int、string或标记为datacontract的自定义复杂类型)与流混合使用

这里有很好的记录:

它说:

对流式传输的限制

使用流传输模式 使运行时强制执行 附加限制

跨应用程序发生的操作 流式传输可以有一个合同 最多有一个输入或输出 参数。该参数对应于 到消息的整个主体,以及 必须是消息,一种派生类型的 流,或IXmlSerializable 实施有返回值的 因为一个操作相当于 具有输出参数的

因此,我想您必须重新构建您的解决方案,使其具有两个方法—一个以复杂类型返回基本信息,另一个处理流式处理的操作


简而言之:您不能将缓冲传输(发送回标记为DataContract的int、string或自定义复杂类型)与流式传输混合使用

这里有很好的记录:

它说:

对流式传输的限制

使用流传输模式 使运行时强制执行 附加限制

跨应用程序发生的操作 流式传输可以有一个合同 最多有一个输入或输出 参数。该参数对应于 到消息的整个主体,以及 必须是消息,一种派生类型的 流,或IXmlSerializable 实施有返回值的 因为一个操作相当于 具有输出参数的

因此,我想您必须重新构建您的解决方案,使其具有两种方法—一种是以co格式返回基本信息