【问题标题】:How to deeply compare non-serializable objects?如何深入比较不可序列化的对象?
【发布时间】:2015-07-07 04:23:51
【问题描述】:

假设我们有两个游标文件,它们被加载到 c# 对象中:

using (var ms = new MemoryStream(Resource.file1))
    _cursor1 = new System.Windows.Input.Cursor(ms);

using (var ms = new MemoryStream(Resource.file2))
    _cursor2 = new System.Windows.Input.Cursor(ms);

我想比较这些对象是有原因的(例如,假设file1 可以是file2 的副本,我想检测它)。我有一个方法试图将对象反序列化为字节数组,以便最终比较这些数组:

public static byte[] ToByteArray(this object obj)
{
    var bf = new BinaryFormatter();
    using (var ms = new MemoryStream())
    {
        bf.Serialize(ms, obj);
        return ms.ToArray();
    }
}

不幸的是用法引发了序列化错误:

var equal = _cursor1.ToByteArray().SequenceEqual(_cursor2.ToByteArray());

附加信息:在程序集中键入“System.Windows.Input.Cursor” 'PresentationCore,版本=4.0.0.0,文化=中性, PublicKeyToken=31bf3856ad364e35' 未标记为可序列化。

比较这些对象的方法是什么?

【问题讨论】:

  • 使用不同的序列化程序?
  • @CodesInChaos:你能详细说明一下吗?

标签: c# .net wpf serialization


【解决方案1】:

比较内存流以检查它们是否相等要容易得多。

您还可以选择要比较的和不比较的。如果您尝试比较 Cursor 对象,则它们可能具有使它们不同的内部数据,即使它们具有相同的形状。

我想你知道如何比较MemoryStreams,否则就直说吧。

编辑:好的。据我所知,这是你唯一的选择。反编译游标类后,几乎所有工作都使用非托管代码完成,因此您将无法访问它。

  [DllImport("user32.dll", BestFitMapping=false, CharSet=CharSet.Auto, EntryPoint="LoadImage", ExactSpelling=false, SetLastError=true, ThrowOnUnmappableChar=true)]
        internal static extern NativeMethods.CursorHandle LoadImageCursor(IntPtr hinst, string stName, int nType, int cxDesired, int cyDesired, int nFlags);

【讨论】:

  • 谢谢,但很遗憾我无法访问这些流。我只能访问游标对象。
  • 我看不出提供的 P/Invoke 有何相关性?
  • @aevitas:游标类内部没有任何状态,因为一切都是通过提供的 pinvoke 完成的,因此即使使用反射也很难获得内部结构。
  • 我知道游标是由非托管代码在内部加载的,但最终该对象存储在内存中的某个位置。有没有办法从内存块中提取这些字节?如果我认为正确,在 C++ 中,您可以使用 memcpy 从光标指针复制 sizeof 个字节,遍历它们并比较相应的字节。
  • @JaroslawWaliszko:您所拥有的只是一个保险箱。我不知道如何找到该安全句柄指向的对象的内存地址。无论如何,不​​能保证具有相同图像的两个游标将具有相同的内存字节,因为它们可以存储除图像之外的其他内容。您需要知道图像存储在内存流中的哪个位置。
猜你喜欢
  • 2022-01-09
  • 1970-01-01
  • 2020-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-02
  • 2021-12-31
  • 2014-03-14
相关资源
最近更新 更多