gpt4 book ai didi

c# - WCF 服务返回 dictionary 数组

转载 作者:太空狗 更新时间:2023-10-29 21:25:37 39 4
gpt4 key购买 nike

我一直在尝试使用 SilverLight 客户端调用将返回 Dictionary<string, object> 的 ASP.Net WCF 服务.当字典中的值是像 int 这样的简单类型时,它工作得很好。 , stringGuid .

但是,我现在有一个场景,我需要其中一个值是 Dictionary<string, object> 的数组。 !一切都编译得很好,服务的签名没有改变,但服务调用现在失败了。

有什么解决办法吗?我试图用 KnownType 注释我的服务类和方法和 ServiceKnownType属性,但这没有用。

这是一段代码:

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
[OperationContract]
[ServiceKnownType(typeof(Dictionary<string, object>))]
public Dictionary<string, object> GetObject()
{
return new Dictionary<string, object>()
{
{ "pty1", 1 },
{ "pty2", Guid.NewGuid() },
{ "pty3", "blah" },
{ "pty4", new Dictionary<string, object>[]
{
new Dictionary<string, object>()
{
{ "pty1", 4 },
{ "pty2", Guid.NewGuid() },
{ "pty3", "blah" },
}
,
new Dictionary<string, object>()
{
{ "pty1", 4 },
{ "pty2", Guid.NewGuid() },
{ "pty3", "blahblah" },
}
}
}
};
}
}

感谢您的回答。我已经打开了 WCF 跟踪,而且正如所怀疑的那样,在序列化过程中出现了问题。问题不在于 Dictionary<string, object> 的序列化但是Array中的一个的 Dictionary<string, object> .

这里是 WCF 服务记录的异常。

There was an error while trying to serialize parameter :GetObjectResult. The InnerException message was 'Type 'System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]][]' with data contract name 'ArrayOfArrayOfKeyValueOfstringanyType:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

我还尝试定义一个新的 DataContract具有单个数据成员的类,但它会导致完全相同的错误。

这是相关代码,后面是 WCF 日志记录的异常。

[DataContract]
[KnownType(typeof(ObjectHolder))]
public class ObjectHolder
{
[DataMember]
public object Object { get; private set; }

public ObjectHolder(object obj)
{
this.Object = obj;
}
}

There was an error while trying to serialize parameter :GetObjectResult. The InnerException message was 'Type 'System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[SilverlightApplication7.Web.ObjectHolder, SilverlightApplication7.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]][]' with data contract name 'ArrayOfArrayOfKeyValueOfstringObjectHolderWAwxSTlb:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

我又玩过 ServiceKnownType对于 ObjectHolder , ObjectHolder[]甚至ObjectHolder[][]因为异常提到了“ArrayOfArrayOfKeyValueOfstringObjectHolder”。

仍然没有解决方案。

最佳答案

首先你应该configure WCF tracing在 app cofig 文件中,可以帮助您了解服务通信背后发生的事情。在这种情况下,您可以轻松获取通信过程中发生的所有错误。

现在,让我们尝试解决您的问题。我几乎相信已知类型的问题。在面向服务的世界中,您应该手动定义所有可以参与服务契约的具体类型,因为 DataContractSerializer 不在序列化对象中提供此类信息。

在这种情况下,这意味着您应该执行以下操作:

[ServiceKnownType(typeof(string))] 
[ServiceKnownType(typeof(Guid))]
[ServiceKnownType(typeof(int))] // but I think DataContractSerializer can deal himself with primitives
[ServiceKnownType(typeof(YourClass))] //UserDefined types you should add manually
public Dictionary<string, object> GetObject()

我还建议您不要在服务契约(Contract)中使用对象,因为它很容易出错。考虑一下,稍后您或您的一位同事修改了一行代码:

new Dictionary<string, object>()
{
{ "pty1", 4 },
{ "pty2", Guid.NewGuid() },
{ "pty3", new SomeClass() }, //OOPS!!!
}

在这种情况下,当您的服务尝试返回此 Dictionary 时,您会遇到运行时故障,因为 DataContractSerializer 不期望此契约中的 SomeClass。

解决这个问题的一种方法是创建单独的类型:

[DataContract]
[KnownType(typeof(Guid))]
[KnownType(typeof(SomeClass1))]
[KnownType(typeof(SomeClass2))]
public class MyType
{
private MyType(object obj) {
Object = obj;
}

public static MyType FromSomeClass1(SomeClass1 c1) {
return new MyType(c1);
}

public static MyType FromSomeClass2(SomeClass2 c2) {
return new MyType(c2);
}

public static MyType FromGuid(Guid guid) {
return new MyType(guid);
}

[DataMember]
public object Object { get; private set; }
}

在这种情况下,如果您想添加一些新类型,您应该添加工厂方法和 KnownTypeAttribute(这种方法更冗长,但不易出错)。

但是,如果您的客户端和服务是在 WCF 上编写的,您可以牺牲面向服务的主要原则并使用 NetDataContractSerializer相反 DataContractSerializer .NetDataContractSerializer 旨在补充 DataContractSerializer。您可以使用 NetDataContractSerializer 序列化一个类型,并使用 DataContractSerializer 反序列化。但是 NetDataContractSerializer 在序列化的 XML 中包含 CLR 类型信息,而 DataContractSerializer 则没有。因此,NetDataContractSerializer 可以用于任何 CLR 类型的序列化和反序列化,而无需任何 KnownTypes 内容。

关于c# - WCF 服务返回 dictionary<string, object> 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2160052/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com