序列化对象消失(BinaryFormatter)

2024-01-07

背景

我有一个对象需要序列化才能传输到高性能计算集群以供以后使用

以前,我为我的对象使用了开箱即用的二进制格式化程序,它代表了统计形状模型,并且一切都很顺利

我的对象变得更加复杂,我决定通过实现 ISerialized 来自定义序列化过程。我继续支持以以前的格式存储的数据

问题

我的问题是,一个特定值似乎序列化成功,但当我尝试反序列化时,其值始终为 null。 (没有错误,只是一个非常令人不快、无用的 null)

当我在序列化点中断时,我可以通过检查 SerializationInfo 看到该对象已添加到 SerializationInfo 中,并且它具有值(这没什么花哨的,但将在下面发布它的代码)

正在调用序列化构造函数(我也在那里放置了一个断点),但是当我检查构造函数的 SerializationInfo 对象时,它没有数据(它确实有一个条目,只是没有数据)

UPDATE- 下载控制台应用程序here https://docs.google.com/file/d/0B_ITQGuqH0C4bDJoZXJGRzd0aUU/edit?usp=sharing。感谢您的关注

或者,查看此处的代码:

The Code

导致问题的类:(PointProfiles 属性是有问题的对象)

   [Serializable]
    public class TrainingSet : ITrainingSet, ISerializable
    {
        public Dictionary<Tuple<int, int>, IPointTrainingSet> PointProfiles { get; set; }

        public PrincipalComponentAnalysis PointPCA { get; set; }

        public double[] AlignedMean { get; set; }

        public List<Tuple<string, ITransform>> Transforms { get; set; }

        public string[] FileNames { get; set; }

        private static Lazy<BinaryFormatter> formatter = new Lazy<BinaryFormatter>();

        public static ITrainingSet Load(Guid modelId)
        {
            ModelSample s = DataProxy<ModelSample>.AsQueryable().Where(m => m.ModelId == modelId).SingleOrDefault();
            if (s == null)
                return null;

            byte[] raw = s.Samples.ToArray();
            using (MemoryStream ms = new MemoryStream(raw))
                return (ITrainingSet)formatter.Value.Deserialize(ms);

        }

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("pca", PointPCA);

            info.AddValue("tp1", PointProfiles.Select(pp => pp.Key.Item1).ToArray());
            info.AddValue("tp2", PointProfiles.Select(pp => pp.Key.Item2).ToArray());

            var x = PointProfiles.Select(pp => (ProfileModel)pp.Value).ToArray();
            info.AddValue("ipts", x, typeof(ProfileModel[]));

            info.AddValue("am", AlignedMean);

            info.AddValue("tname", Transforms.Select(t => t.Item1).ToArray());
            info.AddValue("tval", Transforms.Select(t => t.Item2).ToArray());
            info.AddValue("fnames", FileNames);
            info.AddValue("version", 1);  // nb
        }

        public TrainingSet(SerializationInfo info, StreamingContext context)
        {
            int version = 0;
            foreach(SerializationEntry s in info)
            {
                if(s.Name == "version")
                    version = (int)s.Value;
            }

            switch(version)
            {
                case 0:
                    // old (default binary formatter)
                    PointPCA = info.GetValue("<PointPCA>k__BackingField", typeof(PrincipalComponentAnalysis)) as PrincipalComponentAnalysis;
                    PointProfiles = info.GetValue("<PointProfiles>k__BackingField", typeof(Dictionary<Tuple<int, int>, IPointTrainingSet>)) as Dictionary<Tuple<int, int>, IPointTrainingSet>;
                    AlignedMean = info.GetValue("<AlignedMean>k__BackingField", typeof(double[])) as double[];
                    Transforms = info.GetValue("<Transforms>k__BackingField", typeof(List<Tuple<string, ITransform>>)) as List<Tuple<string, ITransform>>;
                    FileNames = info.GetValue("<FileNames>k__BackingField", typeof(string[])) as string[];

            //stats.PointPCA = pointPCA;
            //stats.PointProfiles = pointProfiles;
            //stats.AlignedMean = alignedMean;
            //stats.Transforms = transforms;
            //stats.FileNames = fileNames;

                    break;

                case 1:
                    FileNames = info.GetValue("fnames", typeof(string[])) as string[];

                    var t = info.GetValue("tval", typeof(ITransform[])) as ITransform[];
                    var tn = info.GetValue("tname", typeof(string[])) as string[];

                    Transforms = new List<Tuple<string, ITransform>>();
                    for(int i = 0;i < tn.Length;i++)
                        Transforms.Add(new Tuple<string,ITransform>(tn[i], t[i]));

                    AlignedMean = info.GetValue("am", typeof(double[])) as double[];

                    PointPCA = info.GetValue("pca", typeof(PrincipalComponentAnalysis)) as PrincipalComponentAnalysis;


                    var ipts = info.GetValue("ipts", typeof(ProfileModel[]));

                    foreach (var x in info) 
                    {
                        int a = 0;
                        a++;   // break point here, info has an entry for key "ipts", but it's null  (or rather an array of the correct length, and each element of the array is null)
                    }

                    var xxx = ipts as IPointTrainingSet[];

                    var i2 = info.GetValue("tp2", typeof(int[])) as int[];

                    var i1 = info.GetValue("tp1", typeof(int[])) as int[];

                    PointProfiles = new Dictionary<Tuple<int, int>, IPointTrainingSet>();
                    for (int i = 0; i < i1.Length; i++)
                        PointProfiles.Add(new Tuple<int, int>(i1[i], i2[i]), xxx[i]);



                    break;

                default:
                    throw new NotImplementedException("TrainingSet version " + version + " is not supported");
            }

        }

        public TrainingSet()
        {

        }
    }

Profile 类(也可序列化,这是接下来列出的 ProfileModel 的基类)

    [Serializable]
    public class Profile : ISerializable, IProfile
    {
        public double Angle { get; private set; }
        public int PointIndex { get; private set; }
        public int Level { get; set; }


        public double[,] G { get; private set; }
        public virtual double[,] GBar { get { throw new InvalidOperationException(); } }

        public virtual int Width { get { return G.Length; } }

        public Profile(int level, int pointIndex, double angle, double[,] G)
        {
            this.G = G;
            PointIndex = pointIndex;
            Level = level;
            Angle = angle;
        }

        // deserialization
        public Profile(SerializationInfo info, StreamingContext context)
        {
            PointIndex = info.GetInt32("p");
            Angle = info.GetDouble("a");
            G = (double[,])info.GetValue("g", typeof(double[,]));

            Level = info.GetInt32("l");

            //_pca = new Lazy<PrincipalComponentAnalysis>(Pca);
        }

        // serialization
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("p", PointIndex);
            info.AddValue("a", Angle);
            info.AddValue("g", G);
            info.AddValue("l", Level);
        }

    }

和(最后)ProfileModel 类:

[Serializable]
public class ProfileModel : Profile, ISerializable, IPointTrainingSet
{

    public IProfile MeanProfile { get; private set; }

    private ProfileModel(int level, int PointIndex, IProfile[] profiles)
        : base(level, PointIndex, 0, null)
    {
        double[,] m = Matrix.Create<double>(profiles.Length, profiles[0].G.Columns(), 0);

        int idx = 0;
        foreach (var pg in profiles.Select(p => p.G.GetRow(0)))
            m.SetRow(idx++, pg);



        Profile meanProfile = new Profile(level, PointIndex, 0, m.Mean().ToMatrix());
        MeanProfile = meanProfile;
    }

    // deserialization
    public ProfileModel(SerializationInfo info, StreamingContext context) : base(info, context) {
        var ps = info.GetValue("mp", typeof(Profile));

        MeanProfile = (IProfile)ps;
    }

    // serialization
    public new void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("mp", MeanProfile, typeof(Profile));
        base.GetObjectData(info, context);
    }

    public override double[,] GBar
    {
        get
        {
            return MeanProfile.G;
        }
    }

    public override int Width { get {
        return GBar.Columns();
    } }
}

如果您能发现我做错的任何事情可能导致这种情况发生,我将非常非常感激:)


首先对数组进行反序列化,然后再执行内部反序列化。当循环遍历 ProfileModel 数组时,其内容尚未被反序列化。

您可以通过实现 IDeserializationCallback (或通过将 OnDeserilized 属性分配给应在反序列化完成时调用的方法)来解决此问题。 OnDeserialzation 方法在整个对象图反序列化后被调用。

您需要将数组存放在私有字段中:

private int []i1;
private int []i2;
private ProfileModel []  ipts;

在反序列化下执行以下操作:

ipts = info.GetValue("ipts", typeof(ProfileModel[]));
i2 = info.GetValue("tp2", typeof(int[])) as int[];
i1 = info.GetValue("tp1", typeof(int[])) as int[];

并实现 IDeserializationCallback:

public void OnDerserilization(object sender)
{
  PointProfiles = new Dictionary<Tuple<int, int>, IPointTrainingSet>();

  for (int i = 0; i < i1.Length; i++)
     PointProfiles.Add(new Tuple<int, int>(i1[i], i2[i]), ipts[i]);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

序列化对象消失(BinaryFormatter) 的相关文章

  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • 如何忽略“有符号和无符号整数表达式之间的比较”?

    谁能告诉我必须使用哪个标志才能使 gcc 忽略 有符号和无符号整数表达式之间的比较 警告消息 gcc Wno sign compare 但你确实应该修复它警告你的比较
  • 使闭包捕获的变量变得易失性

    闭包捕获的变量如何与不同线程交互 在下面的示例代码中 我想将totalEvents 声明为易失性的 但C 不允许这样做 是的 我知道这是错误的代码 这只是一个例子 private void WaitFor10Events volatile
  • 当 contains() 工作正常时,xpath 函数ends-with() 工作时出现问题

    我正在尝试获取具有以特定 id 结尾的属性的标签 like span 我想获取 id 以 国家 地区 结尾的跨度我尝试以下xpath span ends with id Country 但我得到以下异常 需要命名空间管理器或 XsltCon
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限
  • 获取没有非标准端口的原始 url (C#)

    第一个问题 环境 MVC C AppHarbor Problem 我正在调用 openid 提供商 并根据域生成绝对回调 url 在我的本地机器上 如果我点击的话 效果很好http localhost 12345 login Request
  • Json.NET - 反序列化接口属性引发错误“类型是接口或抽象类,无法实例化”

    我有一个类 其属性是接口 public class Foo public int Number get set public ISomething Thing get set 尝试反序列化Foo使用 Json NET 的类给我一条错误消息
  • 在数据库中搜索时忽略空文本框

    此代码能够搜索数据并将其加载到DataGridView基于搜索表单文本框中提供的值 如果我将任何文本框留空 则不会有搜索结果 因为 SQL 查询是用 AND 组合的 如何在搜索 从 SQL 查询或 C 代码 时忽略空文本框 private
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • 如何衡量两个字符串之间的相似度? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给定两个字符串text1 and text2 public SOMEUSABLERETURNTYPE Compare string t
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 为什么我收到“找不到编译动态表达式所需的一种或多种类型。”?

    我有一个已更新的项目 NET 3 5 MVC v2 到 NET 4 0 MVC v3 当我尝试使用或设置时编译出现错误 ViewBag Title财产 找不到编译动态表达式所需的一种或多种类型 您是否缺少对 Microsoft CSharp
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • 如何使用 std::string 将所有出现的一个字符替换为两个字符?

    有没有一种简单的方法来替换所有出现的 in a std string with 转义 a 中的所有斜杠std string 完成此操作的最简单方法可能是boost字符串算法库 http www boost org doc libs 1 46
  • 如何在 C++ BOOST 中像图形一样加载 TIFF 图像

    我想要加载一个 tiff 图像 带有带有浮点值的像素的 GEOTIFF 例如 boost C 中的图形 我是 C 的新手 我的目标是使用从源 A 到目标 B 的双向 Dijkstra 来获得更高的性能 Boost GIL load tiif
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke

随机推荐