有没有办法将C#对象的整个类定义保存到文件/数据存储?
我使用 [Serializable] 标记和 ISerializable 界面来完成此操作,但这两个都是依赖于运行时在程序集中的对象定义。
我正在寻找的是以下场景的解决方案:
1)用户在我的软件中创建对象 MyClass 并保存
出于本示例的目的, MyClass 是一个独立的对象,不依赖于系统中的任何其他类:
即。这可能是整个定义:
public class MyClass
{
public int MyProperty { get; set; }
public void DoSomething() { /* do something, like Console.Write(""); */ }
}
2)我们发布了一个从系统中删除 MyClass 的补丁
3)用户从步骤1加载保存的 MyClass ,并在其上调用 DoSomething() - 该函数的功能与补丁从系统中删除该类之前的功能完全相同
如果没有反射/发出欺骗,有没有办法可以做到这一点?
答案 0 :(得分:3)
不,如果不发出类型定义,这将不起作用。你要做的实际上是保存代码(否则,DoSomething
将如何工作?) - 这是编译器为你做的。简单的序列化在这里永远不会对你有用。
所以,如果你需要保存行为和状态,你需要保留历史代码,使用某种类型的反射发射技巧将类型定义保存为可加载程序集,或使用动态编程技巧处理数据作为可执行代码。
当我之前进行版本化序列化时,我通常在对象上有自定义序列化逻辑和“版本”属性 - 使用此属性我可以创建一个我已移动并重命名的类型 - 比如说SomeClass
到Archive.SomeClassV3
。您可以使用Version Tolerant Serialization,但我更愿意实现ISerializable并使用序列化代理(如果需要)。 (好吧,实际上我更愿意完全避免这个问题!)
答案 1 :(得分:0)
好吧,您可以将所有这些可序列化的类保存在自己的DLL中,将DLL与应用程序打包在一起,并在运行时加载DLL。这样,即使从最新版本的应用程序中删除类,加载的DLL仍然可以工作。
这似乎是一种可怕的方法,但是......现在你有客户端运行古代代码,你甚至不再拥有源代码控制库。你打算怎么调试呢?
答案 2 :(得分:0)
你所说的不是类属性序列化,而是关于进程序列化(或方法 - 无关紧要)。但与属性序列化不同,它应包含在您需要时运行的MSIL代码。因此,您必须以某种方式将其转换为bin代码,然后由Assembly.Load运行。我想这不是一个简单的方法。因此,如果可以的话 - 将MyClass的实现存储到单独的dll中,或者作为字符串(用c#语言)存储,以便通过反射进一步编译和执行。