ExtensionDataObject未标记为可序列化 [英] ExtensionDataObject not marked as serializable

查看:235
本文介绍了ExtensionDataObject未标记为可序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Oi!

我在序列化会话状态时遇到问题.我们有2个组件,即WCF和Web.基于我们的AdministrationPartial.cs和Administration.svc,我们使用以下.bat文件为我们的Web项目生成"Administration.cs"代码:

I'm having issues serializing my session state. We have 2 components, our WCF and Web. Based on our AdministrationPartial.cs and Administration.svc we generate "Administration.cs" code for our web project with the following .bat file :

svcutil.exe http://wcf_url.local/Administration.svc?wsdl /r:"{Path}\{Namespace}.dll" /d:"{Path}\{Namespace}\Code"

我从上述声明中删除了个人数据,并将其替换为{path}和{namespace}. Administration.cs将位于代码映射中.

I removed the personal data from the above statement and replaced it with {path} and {namespace}. The Administration.cs will be inside the Code map.

在Partial中,我们有:

In the Partial we have :

[Serializable]
public partial class MyObject
{
    <Some code>
}

它生成了以下代码:

namespace {mynamespace}
{
          using System.Runtime.Serialization

          [System.Diagnostics.DebuggerStepThroughAttribute()]
          [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
          [System.Runtime.Serialization.DataContractAttribute(Name="MyObject", Namespace="http://schemas.datacontract.org/2004/07/{namespace}")]
          public partial class MyObject : object, System.Runtime.Serialization.IExtensibleDataObject
          {
                    private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
                    ...... generated code

我在做什么错了?

蒂姆

实际错误是:Type 'System.Runtime.Serialization.ExtensionDataObject' in Assembly 'System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.

推荐答案

您的问题似乎是,如何为BinaryFormatter创建一个[Serializable]的类,并为DataContractSerializer?

It appears that your question is, How can I create a class that is [Serializable] for BinaryFormatter and also implements IExtensibleDataObject for DataContractSerializer?

答案是,这不是开箱即用的,因为您已经注意到, 访问内部数据. .datacontractserializer%28v = vs.110%29.aspx"rel =" nofollow> DataContractSerializer .这建议使您的MyObject类可序列化的方法:将扩展数据存储在实现

The answer is that this does not work out of the box since, as you have noticed, ExtensionDataObject is not marked as serializable. Nevertheless it can be done with a bit of extra coding. For whatever reason Microsoft chose to make ExtensionDataObject a completely opaque pointer, with no public properties or other ways to access the data therein. Except that it is possible to access the data inside by re-serializing to XML using DataContractSerializer. This suggests a way to make your MyObject class serializable: store the extension data in a proxy container field that implements ISerializable and, internally, serializes and deserializes the extension data to XML.

以下代理包装器完成了此任务:

The following proxy wrapper accomplishes this task:

[Serializable]
public struct ExtensionDataObjectSerializationProxy : ISerializable
{
    public static implicit operator ExtensionDataObjectSerializationProxy(ExtensionDataObject data) { return new ExtensionDataObjectSerializationProxy(data); }

    public static implicit operator ExtensionDataObject(ExtensionDataObjectSerializationProxy proxy) { return proxy.ExtensionData; }

    private readonly System.Runtime.Serialization.ExtensionDataObject extensionDataField;

    public ExtensionDataObject ExtensionData { get { return extensionDataField; } }

    [DataContract(Name = "ExtensionData", Namespace = "")]
    sealed class ExtensionDataObjectSerializationContractProxy : IExtensibleDataObject
    {
        private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

        #region IExtensibleDataObject Members

        public ExtensionDataObject ExtensionData
        {
            get
            {
                return extensionDataField;
            }
            set
            {
                extensionDataField = value;
            }
        }

        #endregion
    }

    public ExtensionDataObjectSerializationProxy(ExtensionDataObject extensionData)
    {
        this.extensionDataField = extensionData;
    }

    public ExtensionDataObjectSerializationProxy(SerializationInfo info, StreamingContext context)
    {
        var xml = (string)info.GetValue("ExtensionData", typeof(string));
        if (!string.IsNullOrEmpty(xml))
        {
            var wrapper = DataContractSerializerHelper.LoadFromXML<ExtensionDataObjectSerializationContractProxy>(xml);
            extensionDataField = (wrapper == null ? null : wrapper.ExtensionData);
        }
        else
        {
            extensionDataField = null;
        }
    }

    #region ISerializable Members

    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (ExtensionData != null)
        {
            var xml = DataContractSerializerHelper.GetXml(new ExtensionDataObjectSerializationContractProxy { ExtensionData = this.ExtensionData });
            info.AddValue("ExtensionData", xml);
        }
        else
        {
            info.AddValue("ExtensionData", (string)null);
        }
    }

    #endregion
}

public static class DataContractSerializerHelper
{
    public static string GetXml<T>(T obj, DataContractSerializer serializer = null)
    {
        using (var textWriter = new StringWriter())
        {
            using (var xmlWriter = XmlWriter.Create(textWriter))
            {
                (serializer ?? new DataContractSerializer(typeof(T))).WriteObject(xmlWriter, obj);
            }
            return textWriter.ToString();
        }
    }

    public static T LoadFromXML<T>(string xml, DataContractSerializer serializer = null)
    {
        using (var textReader = new StringReader(xml ?? ""))
        using (var xmlReader = XmlReader.Create(textReader))
        {
            return (T)(serializer ?? new DataContractSerializer(typeof(T))).ReadObject(xmlReader);
        }
    }
}

然后手动修改您的MyObject类,如下所示:

Then manually modify your MyObject class as follows:

public partial class MyObject : object, System.Runtime.Serialization.IExtensibleDataObject
{
    private ExtensionDataObjectSerializationProxy extensionDataField; // Use the proxy not ExtensionDataObject directly

    public ExtensionDataObject ExtensionData
    {
        get
        {
            return extensionDataField;
        }
        set
        {
            extensionDataField = value;
        }
    }
}

这篇关于ExtensionDataObject未标记为可序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆