C# 如何序列化具有接口作为属性的对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/821780/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I serialize an object that has an interface as a property?
提问by David Basarab
I have 2 interfaces IA and IB.
我有 2 个接口 IA 和 IB。
public interface IA
{
IB InterfaceB { get; set; }
}
public interface IB
{
IA InterfaceA { get; set; }
void SetIA(IA value);
}
Each interfaces references the other.
每个接口都引用另一个。
I am trying to serialize ClassA as defined below.
我正在尝试按如下定义序列化 ClassA。
[Serializable]
public class ClassA : IA
{
public IB InterfaceB { get; set; }
public ClassA()
{
// Call outside function to get Interface B
IB interfaceB = Program.GetInsanceForIB();
// Set IB to have A
interfaceB.SetIA(this);
}
}
[Serializable]
public class ClassB : IB
{
public IA InterfaceA { get; set; }
public void SetIA(IA value)
{
this.InterfaceA = value as ClassA;
}
}
I get an error when I try too serialize because the 2 properties are interfaces. I want to serialize the properties.
当我尝试序列化时出现错误,因为这 2 个属性是接口。我想序列化属性。
How would I get around this?
我将如何解决这个问题?
I need to have references in each interface to the other. And I need to be able to serialize the class back and forth.
我需要在每个接口中都有对另一个的引用。而且我需要能够来回序列化该类。
采纳答案by Erich Mirabal
You have various bugs in your code, otherwise this would work just fine.
您的代码中有各种错误,否则这会正常工作。
- In the constructor for
ClassA
, your are setting an local variable IB, not the object's IB object. - In
ClassB
, you are casting back to the object concrete class, instead of leaving it alone as the interface type.
- 在 的构造函数中
ClassA
,您设置的是局部变量 IB,而不是对象的 IB 对象。 - 在 中
ClassB
,您将转换回对象具体类,而不是将其单独作为接口类型。
Here is what your code should look like:
您的代码应该如下所示:
public interface IA
{
IB InterfaceB { get; set; }
}
public interface IB
{
IA InterfaceA { get; set; }
void SetIA(IA value);
}
[Serializable]
public class ClassA : IA
{
public IB InterfaceB { get; set; }
public ClassA()
{
// Call outside function to get Interface B
this.InterfaceB = new ClassB();
// Set IB to have A
InterfaceB.SetIA(this);
}
}
[Serializable]
public class ClassB : IB
{
public IA InterfaceA { get; set; }
public void SetIA(IA value)
{
this.InterfaceA = value;
}
}
[STAThread]
static void Main()
{
MemoryStream ms = new MemoryStream();
BinaryFormatter bin = new BinaryFormatter();
ClassA myA = new ClassA();
bin.Serialize(ms, myA);
ms.Position = 0;
ClassA myOtherA = bin.Deserialize(ms) as ClassA;
Console.ReadLine();
}
回答by rein
Assuming you don't want to serialize the interface property, place the following attribute
假设您不想序列化接口属性,则放置以下属性
[NonSerialized]
on the interface property.
在接口属性上。
回答by xtofl
In return for your question: two other questions. What do you Serialize? Is the database reference-aware?
作为您的问题的回报:另外两个问题。你序列化什么?数据库参考感知吗?
You don't serialize interfaces; you serialize objects. The object you serialize is either an implementation of IA or IB.
你不序列化接口;你序列化对象。您序列化的对象是 IA 或 IB 的实现。
It's up to the serialized object to decide whether one of it's properties should be serialized or not. If the property doesneed serializing, it should implement the Serializable interface.
由序列化对象决定是否应该序列化它的属性之一。如果属性确实需要序列化,则它应该实现 Serializable 接口。
You can only serialize a so called 'island' formed by a circular reference A <-> B if the database can identify the serialized objects: it should first 'allocate' space for A, start serializing A's properties. When it arrives at B, it will find one of it's properties referring to A. The serialization should then include a reference to the serialized version of A.
如果数据库可以识别序列化对象,则只能序列化由循环引用 A <-> B 形成的所谓“岛”:它应该首先为 A“分配”空间,然后开始序列化 A 的属性。当它到达 B 时,它将找到引用 A 的属性之一。然后序列化应该包括对 A 的序列化版本的引用。
It's much like two acquaintances moving houses at the same time: first they will exchange their future adresses, only then they will physically move.
这很像两个熟人同时搬家:首先他们会交换他们未来的地址,然后他们才会搬家。
回答by Greg
Implement ISerializable on your objects to control the serialization.
在您的对象上实现 ISerializable 以控制序列化。
[Serializable]
public class ClassB : IB, ISerializable
{
public IA InterfaceA { get; set; }
public void SetIA(IA value)
{
this.InterfaceA = value as ClassA;
}
private MyStringData(SerializationInfo si, StreamingContext ctx) {
Type interfaceAType = System.Type.GetType(si.GetString("InterfaceAType"));
this.InterfaceA = si.GetValue("InterfaceA", interfaceAType);
}
void GetObjectData(SerializationInfo info, StreamingContext ctx) {
info.AddValue("InterfaceAType", this.InterfaceA.GetType().FullName);
info.AddValue("InterfaceA", this.InterfaceA);
}
}
回答by Michael Todd
Interface properties are not serializable. However, fields that reference those properties (in the subclass) are.
接口属性不可序列化。但是,引用这些属性的字段(在子类中)是。
You'll need to do something like this:
你需要做这样的事情:
[Serializable]
public class ClassA : IA
{
private IB _interfaceB;
public IB InterfaceB { get { return _interfaceB; } set { _interfaceB = value; } }
public ClassA()
{
// Call outside function to get Interface B
IB interfaceB = Program.GetInsanceForIB();
// Set IB to have A
interfaceB.SetIA(this);
}
}
[Serializable]
public class ClassB : IB
{
private IA _interfaceA;
public IA InterfaceA { get { return _interfaceA; } set { _interfaceA = value; } }
public void SetIA(IA value)
{
this.InterfaceA = value as ClassA;
}
}