2011-04-03 99 views
0

我想使這種方法成爲RegisterCollection,目的是在DomainObject中註冊一個子對象集合。我的想法是,我想在列表中註冊集合,以便當我在我的DomainObject上調用Save()時,它將調用保存在每個已註冊集合的子域對象上。需要使用通用集合列表來保存域對象中的集合

我製作了這段代碼,但是當我構建時出現這個錯誤:參數類型'OrderCollection'不能分配給參數類型Collection

我使用C#與.NET 3.5。我已經閱讀過.NET 4.0中支持的轉換類型失敗的地方。不知道這是正確的理解,但無論如何,我希望有人有一些建議,還有什麼要做或有一個解決方法。

這可能可能與某種CommandPattern?

public interface IDomainObject 
{ 
    void Save(); 
} 

public class DomainObject : IDomainObject 
{ 
    private readonly IList<Collection<IDomainObject>> m_Collections = new List<Collection<IDomainObject>>(); 

    protected void RegisterCollection(Collection<IDomainObject> collection) 
    { 
     m_Collections.Add(collection); 
    } 

    /// <summary> 
    /// Saves this instance collections. 
    /// </summary> 
    public virtual void Save() 
    { 
     SaveCollections(); 
    } 

    private void SaveCollections() 
    { 
     foreach (var itemCollection in m_Collections) 
     { 
      foreach (var item in itemCollection) 
      { 
       item.Save(); 
      } 
     } 
    } 

} 

public class OrderCollection : Collection<IOrder> 
{ 

} 

public interface IOrder : IDomainObject 
{ 
} 

public class Customer : DomainObject 
{ 
    private readonly OrderCollection m_OrderCollection = new OrderCollection(); 

    public Customer() 
    { 
     // Throws: Argument type 'OrderCollection' is not assignable to parameter type Collection<IDomainObject> 
     RegisterCollection(m_OrderCollection); 
    } 
} 

回答

0

我想我已經找到了解決辦法。它不漂亮,但它的工作。讓我知道你的想法。建議是最受歡迎的。

注意我已經使用了您的一些建議Enzi for RegisterCollection。

這使我可以保持SaveCollections的通用性並在運行時添加更多集合。

public class DomainObject : IDomainObject 
{ 
    private readonly IList<IList> m_Collections = new List<IList>(); 

    protected void RegisterCollection<T>(List<T> collection) where T : IDomainObject 
    { 
     m_Collections.Add(collection); 
    } 

    public int Id { get; set; } 

    /// <summary> 
    /// Saves this instance collections. 
    /// </summary> 
    public virtual void Save() 
    { 
     SaveCollections(); 
    } 

    private void SaveCollections() 
    { 
     foreach (var itemCollection in m_Collections) 
     { 
      foreach (var item in itemCollection)) 
      { 
       ((IDomainObject)item).Save(); 
      } 
     } 
    }   
} 


public interface IDomainObject 
{ 
    /// <summary> 
    /// Gets or sets the id. 
    /// </summary> 
    /// <value> 
    /// The id. 
    /// </value> 
    int Id { get; set; } 

    /// <summary> 
    /// Saves this instance. 
    /// </summary> 
    void Save(); 

    /// <summary> 
    /// Deletes this instance. 
    /// </summary> 
    void Delete(); 
} 
+0

上面進行了編輯以反映更好的解決方案。希望它可以對其他人有用。 – 2011-04-22 09:29:03

0

您的問題是Collection<IOrder>不compatable與Collection<IDomainObject>,這是下降到Covariance and Contravariance

想象的IOrder您的收藏,如果它爲IDomainObject列表處理,那麼這將讓你任何IDomainObject添加到列表中,這意味着我可以添加一個ISomethingElse只要從IDomainObject衍生,顯然這將是一件壞事..

+0

我明白了你的觀點。但是,您能否爲我的問題提出一種替代解決方案,這個解決方案仍然允許我維護一個通用集合列表。 – 2011-04-04 15:07:18

0

你必須維護一個集合清單,或者你可以用一個簡單的清單IDomainObject來代替它嗎?

如果是這樣,你可以只讓RegisterCollection通用:

private readonly IList<IDomainObject> m_Collections = new List<IDomainObject>(); 

protected void RegisterCollection<T>(Collection<T> collection) where T : IDomainObject { 
    foreach (var obj in collection) 
    m_Collections.Add(obj); 
} 

多虧了類型推斷,你將不必指定T並且可以調用RegisterCollection與從IDomainObject派生的類的任何集合。

編輯:好吧,我現在明白你爲什麼要保留列表。我能想到的另一個解決方案是創建一個自定義集合類與非泛型基類:

public abstract class DomainObjectCollection { 
    public abstract void Save(); 
} 

public class DomainObjectCollection<T> : DomainObjectCollection where T : IDomainObject { 
    private readonly Collection<T> collection; 

    public DomainObjectCollection(Collection<T> collection) { 
     this.collection = collection; 
    } 

    public static implicit operator DomainObjectCollection<T> (Collection<T> collection) { 
     return new DomainObjectCollection<T>(collection); 
    } 

    public override void Save() { 
     foreach (var obj in collection) 
      obj.Save(); 
    } 
} 

public class DomainObject : IDomainObject { 
    private readonly IList<DomainObjectCollection> m_Collections = new List<DomainObjectCollection>(); 

    protected void RegisterCollection<T>(Collection<T> collection) where T : IDomainObject { 
     m_Collections.Add((DomainObjectCollection<T>)collection); 
    } 

    /// <summary> 
    /// Saves this instance collections. 
    /// </summary> 
    public virtual void Save() { 
     SaveCollections(); 
    } 

    private void SaveCollections() { 
     foreach (var itemCollection in m_Collections) { 
      itemCollection.Save(); 
     } 
    } 

} 
+0

因爲我想稍後調用Save(),所以我必須維護一個集合列表。使用你的建議,我將最終在Registercollection被調用的時候收集集合中的項目的快照,並因此錯過在Registercollection和Save調用之間添加的對象。希望這是有道理的?無論如何感謝您的建議和努力。 – 2011-04-06 17:21:49