WCF与KnownType for Dictionary一起出现问题

时间:2010-06-09 22:35:45

标签: c# wcf dictionary

我有一个实现以下DataMember的服务:

[DataMember]
public Dictionary<string, List<IOptionQueryResult>> QueryResultItems { get; set; }

我有一个继承自IOptionQueryResult的类“OptionQuerySingleResult”。现在,我明白我需要让OptionQueryResult类型为服务“已知”,因此尝试以各种方式添加KnownType:

[KnownType(typeof(Dictionary<string, OptionQuerySingleResult[]>))]
[KnownType(typeof(Dictionary<string, List<OptionQuerySingleResult>>))]
[KnownType(typeof(OptionQuerySingleResult)]

然而,这些方法都没有起作用,而且在客户端,我要么反序列化失败,要么服务器只是中止了请求,导致连接中止错误。

有没有人知道让这个工作的正确方法是什么? 我想补充一点,如果我将QueryResultItems定义更改为使用具体类型而不是接口,那么一切都运行正常。

谢谢,

汤姆

编辑: 我得到的例外是:

第1行位置524出错。元素“http://schemas.microsoft.com/2003/10/Serialization/Arrays:anyType”包含映射到名称':OptionQuerySingleResult'的类型的数据。反序列化器不知道映射到此名称的任何类型。考虑使用DataContractResolver或将与'OptionQuerySingleResult'对应的类型添加到已知类型列表中 - 例如,通过使用KnownTypeAttribute属性或将其添加到传递给DataContractSerializer的已知类型列表。

但是,当我查看svcutil生成的客户端代理时,其中明确定义了“OptionQuerySingleResult”:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="OptionQuerySingleResult", Namespace="")]
[System.SerializableAttribute()]
public partial class OptionQuerySingleResult : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged 

2 个答案:

答案 0 :(得分:1)

我想你会用:

[KnownType(typeof(OptionQuerySingleResult)]

但是你还需要在OptionQuerySingleResult类上使用[DataContract(Name = "OptionQuerySingleResult")]

我认为这也依赖于SVCUTIL.EXE util生成的客户端代理类。

答案 1 :(得分:0)

您只需将以下属性添加到datacontract类。

[DataMember]
public object UsedForKnownTypeSerializationObject;

现在生成的代理包含您在datacontract上设置的Knowtypes。 我有同样的问题,这是我提出的唯一解决方案。 如果你没有在Object类型的属性上为你的DataContract类, 生成的代理不包含声明的知识类型

例如:

[DataContract]
[KnownType(typeof(List<String>))]
public class Foo
{
    [DataMember]
    public String FooName { get; set; }

    [DataMember]
    public IDictionary<String, Object> Inputs { get; set; }

    [DataMember]
    private Object UsedForKnownTypeSerializationObject{ get; set; }

}

它不是那么漂亮,因为你最终得到一个没有任何虚拟属性 功能实现。但是,我再没有其他解决方案。