有两个程序集:
1)包含序列化程序的程序集。这是序列化和反序列化开始的地方。
2) 包含序列化类型的程序集。这是从第一个程序集调用序列化程序的地方。
assembly1 中的序列化程序的想法很简单。它有两种方法用于将对象从字节数组转换为字节数组。该序列化程序的客户端代码如下所示:
ISerializer serializer = ...
MyClass my = new MyClass();
byte[] data = serializer.Serialize(my);
Console.WriteLine(Encoding.ASCII.GetString(data)); // dump serialized form
MyClass another = (MyClass)serializer.Deserialize(data);
MyClass 是在 assembly2 中定义的,因此 assembly1 对此一无所知。如果序列化器是用标准的 .Net 类实现的,那么该场景将起作用,如下所示:
public class DotNetSerializer : ISerializer
{
public byte[] Serialize(object obj)
{
BinaryFormatter formatter = new BinaryFormatter();
using (MemoryStream stream = new MemoryStream())
{
formatter.Serialize(stream, obj);
byte[] result = stream.GetBuffer();
Array.Resize(ref result, (int)stream.Length);
return result;
}
}
public object Deserialize(byte[] data)
{
BinaryFormatter formatter = new BinaryFormatter();
using (Stream stream = new MemoryStream(data))
{
return formatter.Deserialize(stream);
}
}
}
MyClass 的序列化形式将包含有关定义 MyClass 的程序集的信息。但是,如果序列化器将使用 Java 的类(使用 IKVM 转换)来实现,那么在反序列化期间将抛出 ClassNotFound 异常。这是一个使用 Java 类的序列化器实现:
public class JavaSerializer : ISerializer
{
public object Deserialize(byte[] data)
{
ByteArrayInputStream stream = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(stream);
return ois.readObject();
}
public byte[] Serialize(object obj)
{
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(stream);
oos.writeObject(obj);
stream.flush();
return stream.toByteArray();
}
}
这在 .Net 中不起作用,但如果从 Eclipse 加载插件清单中的附加条目(例如 BuddyPolicy 和 RegisterBuddy),则在 Java 中可以正常工作。我不能只从 JavaSerializer 切换到 DotNetSerializer,因为在我的应用程序(主要用 Java 编写)中有很多 readObject、writeObject、readResolve 等......但我需要以某种方式解决这个问题,所以我寻求解决方案. 目前我看到了一些假设的解决方法:
- 重载 ObjectOutputStream 的某些方法,因此 MyClass 的序列化形式也将包含程序集名称,例如“MyClass,MyAssembly,...”。
- 重载 ObjectInputStream 中的某些方法,因此类将以某种不同的方式加载,也许应该在某些不同的程序集中进行搜索,等等。
- 向程序集清单添加一些信息,以便 IKVM 知道在哪里搜索 MyClass。这是真的吗?这个问题应该如何解决?