问题描述
我有一个有委托成员的类.我可以为该类的每个实例化对象设置委托,但尚未找到任何方法来保存该对象
I have a class which has a delegate member. I can set the delegate for each instantiated object of that class but has not found any way to save that object yet
推荐答案
这是一件非常冒险的事情.
This is a pretty risky thing to do.
虽然您确实可以像任何其他对象一样对委托进行序列化和反序列化,但委托是指向程序内部对其进行序列化的方法的指针.如果你在另一个程序中反序列化对象,你会得到一个 SerializationException
- 如果你幸运的话.
While it's true that you can serialize and deserialize a delegate just like any other object, the delegate is a pointer to a method inside the program that serialized it. If you deserialize the object in another program, you'll get a SerializationException
- if you're lucky.
比如,让我们稍微修改一下darin的程序:
For instance, let's modify darin's program a bit:
class Program
{
[Serializable]
public class Foo
{
public Func<string> Del;
}
static void Main(string[] args)
{
Func<string> a = (() => "a");
Func<string> b = (() => "b");
Foo foo = new Foo();
foo.Del = a;
WriteFoo(foo);
Foo bar = ReadFoo();
Console.WriteLine(bar.Del());
Console.ReadKey();
}
public static void WriteFoo(Foo foo)
{
BinaryFormatter formatter = new BinaryFormatter();
using (var stream = new FileStream("test.bin", FileMode.Create, FileAccess.Write, FileShare.None))
{
formatter.Serialize(stream, foo);
}
}
public static Foo ReadFoo()
{
Foo foo;
BinaryFormatter formatter = new BinaryFormatter();
using (var stream = new FileStream("test.bin", FileMode.Open, FileAccess.Read, FileShare.Read))
{
foo = (Foo)formatter.Deserialize(stream);
}
return foo;
}
}
运行它,你会看到它创建了对象,将其序列化,将其反序列化为一个新对象,当你对新对象调用 Del
时,它会返回a".优秀的.好的,现在注释掉对 WriteFoo
的调用,以便程序只是反序列化对象.再次运行程序,你会得到同样的结果.
Run it, and you'll see that it creates the object, serializes it, deserializes it into a new object, and when you call Del
on the new object it returns "a". Excellent. Okay, now comment out the call to WriteFoo
, so that the program it's just deserializing the object. Run the program again and you get the same result.
现在交换 a 和 b 的声明并运行程序.哎呀.现在反序列化的对象正在返回b".
Now swap the declaration of a and b and run the program. Yikes. Now the deserialized object is returning "b".
发生这种情况是因为实际被序列化的是编译器分配给 lambda 表达式的名称.并且编译器按照找到它们的顺序为 lambda 表达式分配名称.
This is happening because what's actually being serialized is the name that the compiler is assigning to the lambda expression. And the compiler assigns names to lambda expressions in the order it finds them.
这就是这样做的风险:您不是在序列化委托,而是在序列化一个符号.被序列化的是符号的值,而不是符号所代表的内容.反序列化对象的行为取决于该符号的值在反序列化它的程序中代表什么.
And that's what's risky about this: you're not serializing the delegate, you're serializing a symbol. It's the value of the symbol, and not what the symbol represents, that gets serialized. The behavior of the deserialized object depends on what the value of that symbol represents in the program that's deserializing it.
在某种程度上,所有序列化都是如此.将一个对象反序列化为一个程序,该程序以不同于序列化程序的方式实现该对象的类,乐趣就开始了.但是序列化委托将序列化对象耦合到序列化它的程序的符号表,而不是对象类的实现.
To a certain extent, this is true with all serialization. Deserialize an object into a program that implements the object's class differently than the serializing program did, and the fun begins. But serializing delegates couples the serialized object to the symbol table of the program that serialized it, not to the implementation of the object's class.
如果是我,我会考虑明确说明这种耦合.我会创建一个 Foo
的静态属性,它是一个 Dictionary<string, Func<string>>
,用键和函数填充它,并将键存储在每个实例而不是函数.这使得反序列化程序负责在开始反序列化 Foo
对象之前填充字典.在某种程度上,这与使用 BinaryFormatter
序列化委托完全相同;不同之处在于,这种方法使反序列化程序将函数分配给符号的责任更加明显.
If it were me, I'd consider making this coupling explicit. I'd create a static property of Foo
that was a Dictionary<string, Func<string>>
, populate this with keys and functions, and store the key in each instance rather than the function. This makes the deserializing program responsible for populating the dictionary before it starts deserializing Foo
objects. To an extent, this is exactly the same thing that using the BinaryFormatter
to serialize a delegate is doing; the difference is that this approach makes the deserializing program's responsibility for assigning functions to the symbols a lot more apparent.
这篇关于我们可以将代表保存在文件中吗(C#)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!