字典的序列化/反序列化将 dll 注入其他进程时在 C++/CLI 中需要

发布于 2024-11-04 19:50:28 字数 2208 浏览 3 评论 0原文

我需要在 C++/CLI 中序列化一个对象数组 array^,其中包含一个 intPtr 和一个字典 Dictionary code> 其中 ObjectInfo 是一些自定义类。它可以正确序列化,但在反序列化时会出现以下错误:

“System.Runtime.Serialization..SerializationException:无法

加载类型 System.Collections.Generic.Dictionary'2[[System.IntPtr,mscorlib, 版本=4.0.0.0", 文化=中性,PublicKeyToken=............],[System.Collection.Generic.List'1[[SharedObjects.ObjectInfo,SharedObjects,版本......]] 需要反序列化。

我将此 array^ 作为参数传递给 Type->InvokeMember,并且这些参数需要在传递给 InvokeMember 之前进行反序列化

但在反序列化过程中失败。

序列化代码:

     void Serialize(Object^ obj)
     {
        if (obj == nullptr)
        {
           _length = 0;
           return;
        }

     // We could write directly to shared data through an UnmanagedMemoryStream, and
     // catch an error if not big enough. But then we don' get info about how much memory
     // we needed, so instead we write to a dynamically resizing MemoryStream first.

       MemoryStream^ memstream = gcnew MemoryStream();
       BinaryFormatter^ formatter = gcnew BinaryFormatter();
       formatter->Serialize(memstream, obj);
      _length = (int)memstream->Length;

      if (_length > sizeof(_data))
      {
          throw gcnew ApplicationException(String::Format("Not enough shared memory to transfer data (have {0} bytes, but {1} bytes required)", sizeof(_data), _length));
      }

      UnmanagedMemoryStream^ stream = gcnew UnmanagedMemoryStream(_data, _length, _length, FileAccess::Write);
      memstream->WriteTo(stream);
      memstream->Close();
      stream->Close();
   }

反序列化代码

  Object^ Deserialize()
  {
    if (_length == 0)
    {
       return nullptr;
    }

    UnmanagedMemoryStream^ stream = gcnew UnmanagedMemoryStream(_data, _length, _length, FileAccess::Read);
    BinaryFormatter^ formatter = gcnew BinaryFormatter();
    Object^ obj = formatter->Deserialize(stream);
    stream->Close();
    return obj;
  }

I need to serialize an object array array<object^>^ in C++/CLI which contains one intPtr and a dictionary Dictionary<IntPtr,ObjectInfo> where ObjectInfo is some custom class. It is serializing properly but while deserializing it gives this error:

"System.Runtime.Serialization..SerializationException:Unable

to load type
System.Collections.Generic.Dictionary'2[[System.IntPtr,mscorlib,
Version=4.0.0.0",
Cultural=neutral,PublicKeyToken=..............],[System.Collection.Generic.List'1[[SharedObjects.ObjectInfo,SharedObjects,Version....]]
requires deserialization.

I am passing this array<object^>^ to Type->InvokeMember as arguments, and these arguments need to be de-serialized before passing to InvokeMember.

But it fails during deserialization.

Serialize Code:

     void Serialize(Object^ obj)
     {
        if (obj == nullptr)
        {
           _length = 0;
           return;
        }

     // We could write directly to shared data through an UnmanagedMemoryStream, and
     // catch an error if not big enough. But then we don' get info about how much memory
     // we needed, so instead we write to a dynamically resizing MemoryStream first.

       MemoryStream^ memstream = gcnew MemoryStream();
       BinaryFormatter^ formatter = gcnew BinaryFormatter();
       formatter->Serialize(memstream, obj);
      _length = (int)memstream->Length;

      if (_length > sizeof(_data))
      {
          throw gcnew ApplicationException(String::Format("Not enough shared memory to transfer data (have {0} bytes, but {1} bytes required)", sizeof(_data), _length));
      }

      UnmanagedMemoryStream^ stream = gcnew UnmanagedMemoryStream(_data, _length, _length, FileAccess::Write);
      memstream->WriteTo(stream);
      memstream->Close();
      stream->Close();
   }

Deserialize Code

  Object^ Deserialize()
  {
    if (_length == 0)
    {
       return nullptr;
    }

    UnmanagedMemoryStream^ stream = gcnew UnmanagedMemoryStream(_data, _length, _length, FileAccess::Read);
    BinaryFormatter^ formatter = gcnew BinaryFormatter();
    Object^ obj = formatter->Deserialize(stream);
    stream->Close();
    return obj;
  }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

◇流星雨 2024-11-11 19:50:28

我尝试了你的代码,它与自定义可序列化类完美配合。

您是否尝试使用简单的可序列化类来确保 _data 值在反序列化之前不会损坏?

您的序列化和反序列化代码是否在同一个程序集中?也许您有 2 个程序集引用包含自定义 ShareObject.ObjectInfo 类的程序集的不同版本。

这是我的测试代码:

using namespace System;
using namespace System::IO;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
using namespace System::Runtime::Serialization::Formatters::Binary;

System::Byte* _data;
int _length;

void Serialize(Object^ obj)
{
  MemoryStream^ memstream = gcnew MemoryStream();
  BinaryFormatter^ formatter = gcnew BinaryFormatter();
  formatter->Serialize(memstream, obj);
  _length = (int)memstream->Length;

  UnmanagedMemoryStream^ stream = gcnew UnmanagedMemoryStream(_data, _length, _length, FileAccess::Write);
  memstream->WriteTo(stream);
  memstream->Close();
  stream->Close();
}

Object^ Deserialize()
{
  UnmanagedMemoryStream^ stream = gcnew UnmanagedMemoryStream(_data, _length, _length, FileAccess::Read);
  BinaryFormatter^ formatter = gcnew BinaryFormatter();
  Object^ obj = formatter->Deserialize(stream);
  stream->Close();
  return obj;
}

[SerializableAttribute]
ref class SerializableClass
{
public:
  IntPtr ptr;
  String^ string;
  List<SerializableClass^>^ list;
 };

int main(array<String ^> ^args)
{
  IntPtr ptr = Marshal::AllocHGlobal(1000);
  _data = (System::Byte*)ptr.ToPointer();

  array<SerializableClass^>^ arr = gcnew array<SerializableClass^>(2);
  for (int i = 0; i < arr->Length; i++)
  {
    SerializableClass^ c = gcnew SerializableClass();
    c->ptr = System::IntPtr(1234);
    c->list = gcnew List<SerializableClass^>();

    SerializableClass^ c2 = gcnew SerializableClass();
    c2->string = "Value";
    c->list->Add(c2);
    c->list->Add(c2);

    arr[i] = c;
  }

  Serialize(arr);

  array<SerializableClass^>^ deserializedClass = dynamic_cast<array<SerializableClass^>^>(Deserialize());

  return 0;
}

I tried your code and it works perfectly with a custom serializable class.

Did you try your code with a simple serializable class to ensure _data value is not corrupt before deserialization?

Is your serialization and deserialization code in same assembly? Maybe you have 2 assemblies referencing different versions of your assembly containing your custom ShareObject.ObjectInfo class.

Here is my test code:

using namespace System;
using namespace System::IO;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
using namespace System::Runtime::Serialization::Formatters::Binary;

System::Byte* _data;
int _length;

void Serialize(Object^ obj)
{
  MemoryStream^ memstream = gcnew MemoryStream();
  BinaryFormatter^ formatter = gcnew BinaryFormatter();
  formatter->Serialize(memstream, obj);
  _length = (int)memstream->Length;

  UnmanagedMemoryStream^ stream = gcnew UnmanagedMemoryStream(_data, _length, _length, FileAccess::Write);
  memstream->WriteTo(stream);
  memstream->Close();
  stream->Close();
}

Object^ Deserialize()
{
  UnmanagedMemoryStream^ stream = gcnew UnmanagedMemoryStream(_data, _length, _length, FileAccess::Read);
  BinaryFormatter^ formatter = gcnew BinaryFormatter();
  Object^ obj = formatter->Deserialize(stream);
  stream->Close();
  return obj;
}

[SerializableAttribute]
ref class SerializableClass
{
public:
  IntPtr ptr;
  String^ string;
  List<SerializableClass^>^ list;
 };

int main(array<String ^> ^args)
{
  IntPtr ptr = Marshal::AllocHGlobal(1000);
  _data = (System::Byte*)ptr.ToPointer();

  array<SerializableClass^>^ arr = gcnew array<SerializableClass^>(2);
  for (int i = 0; i < arr->Length; i++)
  {
    SerializableClass^ c = gcnew SerializableClass();
    c->ptr = System::IntPtr(1234);
    c->list = gcnew List<SerializableClass^>();

    SerializableClass^ c2 = gcnew SerializableClass();
    c2->string = "Value";
    c->list->Add(c2);
    c->list->Add(c2);

    arr[i] = c;
  }

  Serialize(arr);

  array<SerializableClass^>^ deserializedClass = dynamic_cast<array<SerializableClass^>^>(Deserialize());

  return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文