无法序列化 System.Collections.Generic.Dictionary`2 类型的成员 ...,因为它实现了 IDictionary

2024-04-30

我试图通过 WCF 传递一个带有 Dictionary 属性的类,对于一种方法失败,但对于另一种方法有效。当类在 a 内返回时List, 有用。但是当类在 a 中返回时DataTable,客户端只是说连接已断开并且没有显示错误。

这是引起问题的类:

[DataContract]
public class DetailLog
{
    [DataMember]
    public string Name
    {
        get;
        set;
    }

    [DataMember]
    public string SubAction
    {
        get;
        set;
    }

    [DataMember]
    public Dictionary<string, string> Fields
    {
        get;
        set;
    }

    [DataMember]
    public string UserName
    {
        get;
        set;
    }
}

我开始创建一个没有问题的方法:

public List<DetailLog> GetDetailLog(List<int> IDs, List<int> actionTypeIds, List<int> userIds, DateTime beginDate, DateTime endDate)

然后我们需要创建一些非常动态的报告,因此我使用了我们之前用于其他动态报告的数据表。

但我需要传递 DetailLog 类,因此我创建了该类型的 DataTable 列:

public DataTable GetCustomDetailReport(int CustomReportID, List<CustomReportFilter> reportFilters)
{
DataTable data = new DataTable();
...
data.Columns.Add("DetailLog", typeof(DetailLog));
...
}

此方法在 WCF 主机端可以正常退出,但在客户端会出现连接丢失的错误。我尝试在界面中为OperationContract添加ServiceKnownType,但没有修复它:

[OperationContract]
[ServiceKnownType(typeof(DetailLog))]
DataTable GetCustomUserAuditReport(int CustomReportID, List<CustomReportFilter> reportFilters);

当该方法返回 DataTable 时,我无法真正调试序列化,因此我将此代码添加到 GetCustomDetailReport() 的末尾以捕获错误。

DataContractSerializer ser = new DataContractSerializer(typeof(DataTable), new List<Type> { typeof(DetailLog) });
ser.WriteObject(Stream.Null, data);

当我这样做时,我看到了一个异常

Cannot serialize member ... of type System.Collections.Generic.Dictionary`2 because it implements IDictionary.

您的问题如下:

  1. Dictionary<TKey, TValue>是由数据契约序列化器 https://msdn.microsoft.com/en-us/library/ms731072%28v=vs.110%29.aspx在 WCF 中使用,如docs https://msdn.microsoft.com/en-us/library/ms731923%28v=vs.110%29.aspx。这就是为什么你的DetailLog类可以由 WCF 作为根对象成功地通过线路发送。

  2. 该序列化器还支持IXmlSerializable https://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable(v=vs.110).aspx允许类型手动将自身序列化为 XML。

  3. DataTable https://msdn.microsoft.com/en-us/library/system.data.datatable%28v=vs.110%29.aspx实施IXmlSerializable.

  4. 在内部,DataTable序列化非原始条目using XmlSerializer https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer%28v=vs.110%29.aspx-- 一个完全不同的序列化器,使用完全不同的代码库。

  5. XmlSerializer不支持字典 https://msdn.microsoft.com/en-us/library/ms950721.aspx。因此你的DetailLog无法通过 WCF 有线发送当嵌套在DataTable.

  6. 作为一个无关的问题,你还需要设置数据表名,如果不设置,序列化会抛出异常:

        data.TableName = "CustomDetailReport"; // For instance
    

要解决字典问题,您需要使您的DetailLog两个序列化器都可以序列化类。问题如何序列化/反序列化Dictionary<int, string>来自不使用 XElement 的自定义 XML? https://stackoverflow.com/questions/12554186/how-to-serialize-deserialize-to-dictionaryint-string-from-custom-xml-not-us给出了多种方法来序列化其字典属性,包括使用代理数组属性:

[XmlType("KeyValue"), XmlRoot("KeyValue")]
public class SerializableKeyValuePair<TKey, TValue>
{
    public TKey Key { get; set; }
    public TValue Value { get; set; }
}

public static class SerializableKeyValuePairExtensions
{
    public static SerializableKeyValuePair<TKey, TValue> ToSerializablePair<TKey, TValue>(this KeyValuePair<TKey, TValue> pair)
    {
        return new SerializableKeyValuePair<TKey, TValue> { Key = pair.Key, Value = pair.Value };
    }
}

[DataContract]
public class DetailLog
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public string SubAction { get; set; }

    [DataMember]
    [XmlIgnore]
    public Dictionary<string, string> Fields { get; set; }

    [IgnoreDataMember]
    [XmlArray("Fields")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public SerializableKeyValuePair<string, string>[] FieldsArray
    {
        get
        {
            return Fields == null ? null : Fields.Select(p => p.ToSerializablePair()).ToArray();
        }
        set
        {
            Fields = value == null ? null : value.ToDictionary(p => p.Key, p => p.Value);
        }
    }

    [DataMember]
    public string UserName { get; set; }
}

WCF 现在应该能够发送您的DataTable成功通过电线。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法序列化 System.Collections.Generic.Dictionary`2 类型的成员 ...,因为它实现了 IDictionary 的相关文章

  • Qt 5 和 QProcess 使用信号/槽 read 重定向标准输出

    这个问题困扰着我 因为它应该有效 但遗憾的是它没有 我试图实现的是读取某个进程的标准输出并让另一个进程处理它 即打印出来 产生输出的过程如下所示 include
  • C# 从带引号的字符串中删除分隔符

    我正在编写一个程序 必须从文本文件中带引号的字符串中删除分隔符 例如 Hello my name is world 必须 Hello my name is world 起初这听起来很简单 我认为是这样 但是您需要检测引号何时开始 何时结束
  • do { ... } while (0) — 它有什么用? [复制]

    这个问题在这里已经有答案了 我已经看到这个表情十多年了 我一直在努力思考它有什么好处 因为我主要在 defines 中看到它 所以我认为它对于内部作用域变量声明和使用中断 而不是 gotos 很有用 对其他方面有好处吗 你用它吗 这是 C
  • 无捕获 lambda 是结构类型吗?

    P1907R1 http www open std org jtc1 sc22 wg21 docs papers 2019 p1907r1 html 接受 C 20 引入结构类型 它们是非类型模板参数的有效类型 GCC 和 Clang 都接
  • 创建动态对象

    如何动态创建对象 string columnNames EmpName EmpID PhoneNo List
  • 使用 C# 使用证书进行 SSL 客户端身份验证

    我需要创建一个 C 应用程序 该应用程序必须使用 SSL 向服务器发送 API 请求 我需要创建客户端身份验证 我已经拥有服务器 CA 证书 客户端证书 cer 客户端私钥 pem 和密码 我找不到有关如何创建客户端连接的示例 有人可以建议
  • 如何在 IIS 中将 WCF 与 basichttpbinding only、SSL 和基本身份验证结合使用?

    是否可以仅使用 IIS 中的 SSL 和基本身份验证来设置 WCF 服务BasicHttpBinding binding 我无法使用wsHttpBinding binding 该站点托管在 IIS 7 上 并设置了以下身份验证 匿名访问 O
  • 如何从 nuget 包中排除子目录和内容

    所以我有一个网站正在尝试打包用于 Octopus Deploy 我有以下文件夹结构 Web Views WantThis Dontwantthis WantThis1 WantThis2 lots more Scripts 我试图排除 Do
  • 如何使用 VB.NET 或 C#.NET 代码从 yahoo 邮件 ID 发送邮件

    我想从我的 yahoomail Id 发送邮件 如何使用 VB NET 或 C NET 代码从 yahoo mail Id 发送邮件 需要善意的帮助 提前谢谢 西瓦库马尔 以下是一些制作基本 html 电子邮件消息的示例 http help
  • 为什么 ATOMIC_FLAG_INIT 为假?

    In C 11有std atomic flag这对于线程循环很有用 static std atomic flag s done ATOMIC FLAG INIT void ThreadMain while s done test and s
  • WCF - 将空元素转换为可为空的本机类型

    将 SOAP 字段元素留空会导致本机类型出现强制转换错误 遗憾的是 由于客户端限制 无法使用 xsi nil true 将 WCF 协定本机类型标记为 nullable 似乎不足以阻止将以下错误返回给客户端 字符串 不是有效的布尔值 在 S
  • 命名空间中不存在类型或命名空间名称 - 但命名空间确实存在

    我已经工作了很长时间没有任何问题的项目突然开始抛出错误 例如 The type or namespace name xxx does not exist in the namespace yyy are you missing an ass
  • GridView必须添加到表单标签中才能渲染

    TextWriter tr new StringWriter HtmlTextWriter writer new HtmlTextWriter tr HtmlForm form new HtmlForm form Controls Add
  • 数据绑定问题,请解释

    public partial class Form1 Form MyClass myClass new MyClass one two public Form1 InitializeComponent textBox1 DataBindin
  • Time 方法在另一个线程中执行并在超时时中止

    您好 我正在尝试异步运行方法 以便计算持续时间并在超过超时时取消该方法 我尝试使用异步和等待来实现这一点 但没有运气 也许我过度设计了这个 任何输入都会受到赞赏 应该注意的是 我无法更改接口 TheirInterface 因此得名 到目前为
  • 了解C/C++中函数调用的堆栈框架? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我也是 C C 和汇编语言的新手 这
  • 在信号/槽处理期间删除 QObject

    我知道从槽处理中删除 QObject 可能会使应用程序崩溃 因为它可能有其他排队的事件 因此 我将使用 obj gt deleteLater 而不是使用 delete obj 据我所知 obj 等待处理所有排队的事件 然后 删除 obj Q
  • 将base64字符串转换为图像c#时出错

    我想在我的网页上显示图像 并单击应该下载的链接按钮 存储的图像文件以二进制格式存储在db中 将 base64 字符串转换为图像时显示错误 详细信息如下 帮助我找到合适的解决方案 谢谢 Error Code protected void Pa
  • Fluent Validation 将 CustomAsync 更改为 MustAsync

    有人可以帮我解决这个问题吗 我正在努力改变CustomAsync 到 MustAsync 但我无法让事情发挥作用 下面是我的自定义方法 RuleFor o gt o MustAsync o gt return CheckIdNumberAl
  • qt 如何知道按钮被点击?

    我正在尝试编写一个程序 用声音进行一些操作 我的问题是我有 3 个播放按钮和 3 个标签 我希望无论我单击 播放 按钮 都应该播放按钮附近标签中名称的声音 我有一个没有任何参数的播放插槽 那么 如何分别连接到每个播放按钮和每个标签呢 实际上

随机推荐