2012-07-04 127 views
0

我有一個Model類,其中包含Message s和Signal s的列表。當Xml(De)序列化時維護多對多關係

每個Message可以包含0個,1個或多個信號。 A Signal可以同時包含0個,1個或更多個消息。在使用XmlSerializer進行反序列化時,我在維護消息和信號之間的關係時遇到了問題,同時也避免了重複的對象(在我的應用程序中,除了XmlSerializer之外,不可能使用其他任何東西)。

class Model 
{ 
    private MessageCollection messages; 
    public MessageCollection Messages { get { return messages; } } 

    private SignalCollection signals; 
    public SignalCollection Signals { get { return signals; } } 

    public Model() 
    { 
     // the collection classes automatically set the Model property of any 
     // Messages/Signals added to its appropriate owner (this) 
     this.messages = new MessageCollection(this); 
     this.signals = new SignalCollection(this); 
    } 
} 

class Message 
{ 
    [XmlIgnore] // set by MessageCollection 
    public Model Model { get; set; } 

    public List<Signal> Signals 
    { 
     get { ??? } 
    } 
} 

class Signal 
{ 
    [XmlIgnore] // set by SignalCollection 
    public Model Model { get; set; } 

    public List<Message> Messages 
    { 
     get { return this.Model.Messages.Where(x => x.Signals.Contains(this)).ToList(); } 
    } 
}

我有想法存儲List<uint> SignalIndicesMessage類,它包含了信號的指標,因爲它們是在Model.Signals列表。但是,假設XmlSerializer在序列化/反序列化時不會弄亂索引是否安全?此外,這種方法意味着Message.Signals獲取[XmlIgnore]屬性,並依賴於使用SignalIndices列表的另一個Linq,以實現與Signal.Messages類似的事情。

換句話說,是否有可能通過與MessageCollection和SignalCollection類一起使用的類似技術來確保所有時間的數據一致性(也是在反序列化過程中,其中對象構造的順序未定義),同時在不使用Linq的Message類中有一個「真實」的信號列表(List<Signal>)?

回答

1

如果添加一個唯一的ID這兩個消息和信號的選項,那麼你可以添加一個新的MessageSignals單例類,它將序列化爲Message ID和Signal ID的Key Value對。然後,您可以序列化和反序列化所有消息,所有信號和所有消息信號配對。這樣,你會使用MessageSignal類作爲查找用於獲取所有信號的消息

public IEnumerable<Signal> Signals 
    { 
    get 
    { 
     return from signal in Signals 
     from ms in MessageSignals 
     where ms.MessageId == this.MessageId && ms.SignalId==signal.Id 
     select signal; 
    } 
    } 

它非常類似於多少一對多的關係,大多數數據庫進行處理。

+0

我不確定爲什麼我沒有這個想法,因爲我在數據庫中也完成了這個想法。儘管我沒有額外的單身人士課程,但我只是通過將ID僅添加到信號並在消息中具有SignalID列表來實現它。 Singleton方法基本上就是我的版本,但與所有消息交叉。起初我並沒有這麼做,因爲Message.Signals和Signal.Message都是Linqed,但我對Linq的性能再次感到驚訝。儘管如此,我寧願在反序列化的時候將結果「緩存」在實際列表中... – dialer

+0

可能是更好的方法。序列化和反序列化singletons總是有點噩夢。 –

1

如果參考模型的signalcollection裏面純粹是爲了設置模型屬性,你可以使用一個signalcollection類消息本身

class Message 
{ 
    [XmlIgnore] // set by MessageCollection 
    public Model Model { get{return signals==null ? null : signals.Model;} set{signals=new SignalCollection(value);} } 

    SignalCollection signals; 
    public SignalCollection Signals 
    { 
     get { return signals; } 
    } 
} 

裏面還是有一個新的信號類從暴露的模型列表導出屬性。

如果上面是不是你可以添加一個方法,模型,火災反序列化後(通過使用OnDeserializedAttribute

class Model 
{ 
    [OnDeserialized] 
    private void restoreModelSignals(StreamingContext context) 
    { 
     //bit of linq here though 
     foreach(var s in messages.SelectMany(m=>m.Signals)) 
      s.Model=this; 
    } 
} 
+0

第一個選項不起作用,因爲消息被反序列化的那一刻,'signals'不能被構造,因爲模型在構造時需要傳遞給'SignalCollection'是未知的。有了這個屬性序列化和反序列化會導致重複'Signal'和'Model'對象。然而,使用OnserializedAttribute和Mark Green的答案可能是一個非常好的解決方案。 – dialer

+0

好吧,現在我很傷心,因爲XmlSerializer不支持像OnDeserializedAttribute這樣的方法的序列化回調。 – dialer