Как я могу сериализовать объект, который имеет интерфейс как свойство? - PullRequest
8 голосов
/ 05 мая 2009

У меня 2 интерфейса IA ​​и IB.

public interface IA
{
    IB InterfaceB { get; set;  }
}

public interface IB
{
    IA InterfaceA { get; set;  }

    void SetIA(IA value);
}

Каждый интерфейс ссылается на другой.

Я пытаюсь сериализовать 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;
    }
}

Я получаю ошибку, когда пытаюсь слишком сериализовать, потому что 2 свойства являются интерфейсами. Я хочу сериализовать свойства.

Как бы мне обойти это?

Мне нужно иметь ссылки в каждом интерфейсе на другой. И мне нужно иметь возможность сериализовать класс туда и обратно.

Ответы [ 5 ]

10 голосов
/ 05 мая 2009

В вашем коде есть различные ошибки, в противном случае это будет нормально работать.

  1. В конструкторе для ClassA вы устанавливаете локальную переменную IB, а не объект IB объекта.
  2. В ClassB вы приводите обратно к конкретному классу объекта, а не оставляете его в качестве типа интерфейса.

Вот как должен выглядеть ваш код:

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();
}
2 голосов
/ 05 мая 2009

Реализация 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);
  }
}
0 голосов
/ 05 мая 2009

Свойства интерфейса не сериализуются. Однако поля, которые ссылаются на эти свойства (в подклассе), являются.

Вам нужно будет сделать что-то вроде этого:

[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;
    }
}
0 голосов
/ 05 мая 2009

В ответ на ваш вопрос: еще два вопроса. Что вы сериализуете? Справляется ли база данных?

Вы не сериализуете интерфейсы; Вы сериализуете объекты. Сериализуемый вами объект является реализацией IA или IB.

Сериализованный объект должен решить, следует ли сериализовать одно из его свойств. Если свойство нуждается в сериализации , оно должно реализовать интерфейс Serializable.

Вы можете сериализовать так называемый «остров», образованный круговой ссылкой A <-> B, только если база данных может идентифицировать сериализованные объекты: она должна сначала «выделить» пространство для A, начать сериализацию свойств A. Когда он достигнет B, он найдет одно из своих свойств, относящихся к A. Затем сериализация должна включать ссылку на сериализованную версию A.

Это похоже на то, как двое знакомых переезжают в одно и то же время: сначала они обменяются своими будущими адресами, только потом они будут физически двигаться.

0 голосов
/ 05 мая 2009

Если вы не хотите сериализовать свойство интерфейса, поместите следующий атрибут

[NonSerialized]

в свойстве интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...