2012-11-07 76 views
2

我有一個應用程序,它具有數據樹作爲數據包終端。爲了實現MVVM模式,我有一個封裝數據樹的邏輯層。因此邏輯也被安排在一棵樹中。如果輸入處於有效狀態,則應將數據複製到第二個線程,該線程用作最後一個有效狀態的雙緩衝區。因此,一種方法是克隆。使用MVVM實現的WPF應用程序的不可變數據模型

另一種方法是將完整的數據後端實現爲不可變的。如果輸入新內容,這意味着要重建整個數據樹。我的問題是,是否有切實可行的方法來做到這一點?我被困在了必須重新分配數據樹到邏輯層的地步。

**更新 - 一些代碼

我們正在做的是我們用它來運行我們的實驗抽象的硬件設備。因此我們定義了「機箱,序列,卡片,頻道,步驟」等類。那些建立一個樹形結構是這樣的:

      Chassis 
         / \ 
        Sequence1  Sequence2 
       / | \ 
       Card1 Card2 Card3 
      / \ 
    Channel1  Channel2 
    /  \ 
Step1  Step2 

在代碼中,它看起來是這樣的:

public class Chassis{ 

readonly var List<Sequence> Sequences = new List<Sequence>(); 

} 

public class Sequence{ 

readonly var List<Card> Cards = new List<Card>(); 

} 

等。當然,每個班級都有更多的屬性,但這些屬性很容易處理。我現在的問題是List是一個可變對象。我可以調用List.Add()並更改它。好吧,有一個ReadOnlyList,但我不確定它是否以正確的方式實現了不變性。正如通過值複製而不是引用,而不僅僅是阻塞通過阻塞設置方法來寫入它。 接下來的問題是序列的數量和步驟可能會有所不同。出於這個原因,我需要列表元素的原子交換。 目前我還沒有更多的代碼,因爲我還在想如果這種方式對我有幫助,並且如果有可能在合理的時間內實現它的話。

+2

對於MVVM應用程序支持不可變模型非常不直觀。我會考慮另一種模式。 –

+0

我遇到了將複雜的不可變模型映射到MVVM的情況,它看起來並不簡單。你到底是怎麼解決這個問題的? –

回答

0

我不知道我是否理解100%你問的是什麼。這聽起來像你有一個特定狀態的對象樹,並且你想要在一個副本上執行一些處理而不修改原始對象狀態。您應該通過「深度複製」來觀察克隆。 This question應該讓你開始。

如果您正在尋找實現一個不可變列表,你可以嘗試儲存該列表爲私有成員,但響應布蘭登債券評論暴露出公共IEnumerable<>

public class Chassis 
{ 

    List<Sequence> _sequences = new List<Sequence>(); 
    public IEnumerable<Sequence> Sequences { get { return _sequences; } } 

} 

18/04/13更新

在Brandon Bonds中鏈接的圖書館肯定是有趣的,並提供優於IEnumerable<>。在很多情況下,這可能是更好的解決方案。但是,如果您使用此庫,則應注意一些警告。

  1. 截至18/04/2013這是一個測試版庫。它顯然還在開發中,可能還沒有準備好用於生產。例如,鏈接文章中用於列表創建的代碼示例在當前nuget包中不起作用。

  2. 這是一個.net 4.5庫。所以它不適合針對舊框架的程序。

  3. 它不保證只包含集合本身的集合中包含的對象的不變性。可以修改不可變列表中的對象您仍然需要考慮用於複製集合的深層副本。

這是在文章

Q的末在常見問題解決:我只能存儲在這些不可改變的集合不可改變的數據?

答:您可以將所有類型的數據存儲在這些集合中。唯一不可變的方面是集合本身,而不是它們包含的項目。

此外,下列代碼示例說明了這一點(使用版本1.0.8-β)

class Data 
{ 
    public int Value { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var test = ImmutableList.Create<Data>();   
     test = test.Add(new Data { Value = 1 }); 
     Console.WriteLine(test[0].Value); 
     test[0].Value = 2; 
     Console.WriteLine(test[0].Value); 
     Console.ReadKey(); 
    } 
} 

此代碼將允許該數據對象的修改和輸出

1 
2 

這裏是一些關於這個話題的文章

3

注意,有新immutable collections for .NET,可以幫助你實現你的目標。

約戴夫·特維的說法非常謹慎(我會downvote /評論,如果我能):

如果您正在尋找實現一個不可變列表,你可以嘗試儲存該列表作爲一個私有成員,但露出公開IEnumerable<>

這是不正確的。私人成員仍然可以通過其容器類更改。公衆成員可以投射到List<T>,IList<T>ICollection<T>而不會引發異常。因此,任何取決於公衆不變性的事物都可能會中斷。

+0

Brandon,請參閱我的更新,瞭解使用不可變集合庫時的一些注意事項 –

相關問題