0
我從this article開始獲取不同類型的MutableKey集合。帶MutableKey的KeyedCollection
我想爲我的所有集合的抽象KeyedCollection基類,所以我使用泛型和我的目的一個接口,但我想知道如果有一個更優雅的解決方案,以避免暴露集合屬性我的物品。
public class FooItem : IMyKeyedCollectionItem<FooItem>
{
// *** In this way the setter of the Collections property is public, any other solution to avoid this? **//
public HashSet<MyKeyedCollectionBase<FooItem>> Collections { get; set; } = new HashSet<MyKeyedCollectionBase<FooItem>>();
private string _name;
public string Name
{
get { return _name; }
set
{
if (Collections != null)
{
foreach (var collection in Collections)
{
collection.ChangeKey(this, value);
}
}
_name = value;
}
}
}
/// <summary>
/// Interface for the mutablekey keyedcollection.
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IMyKeyedCollectionItem<T> where T : IMyKeyedCollectionItem<T>
{
/// <summary>
/// Collections that contain this item.
/// </summary>
HashSet<MyKeyedCollectionBase<T>> Collections { get; set; }
}
// KeyedCollection is an abstract class, so I have to derive
public abstract class MyKeyedCollectionBase<T> : KeyedCollection<string, T> where T : IMyKeyedCollectionItem<T>
{
public MyKeyedCollectionBase() : base(StringComparer.OrdinalIgnoreCase, 0) { } // case-insensitive
public MyKeyedCollectionBase(MyKeyedCollectionBase<T> collection)
{
if (collection != null)
{
foreach (var item in collection)
Add(item);
}
}
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
AddCollectionToItem(item);
}
private void AddCollectionToItem(T item)
{
if (item.Collections == null)
item.Collections = new HashSet<MyKeyedCollectionBase<T>>();
item.Collections.Add(this);
}
private void RemoveCollectionFromItem(T item)
{
item.Collections.Remove(this);
if (item.Collections.Count == 0)
item.Collections = null;
}
protected override void SetItem(int index, T item)
{
var replaced = Items[index];
base.SetItem(index, item);
AddCollectionToItem(item);
RemoveCollectionFromItem(replaced);
}
protected override void RemoveItem(int index)
{
var removedItem = Items[index];
base.RemoveItem(index);
RemoveCollectionFromItem(removedItem);
}
protected override void ClearItems()
{
foreach (var removed in Items)
RemoveCollectionFromItem(removed);
base.ClearItems();
}
// Expose this method internally to allow mutable item keys: When the key for an item changes, this method is used to change the key in the lookup dictionary
internal virtual void ChangeKey(T item, string newKey)
{
base.ChangeItemKey(item, newKey);
}
}
public class MyFooKeyedCollection : MyKeyedCollectionBase<FooItem>
{
protected override string GetKeyForItem(FooItem item)
{
return item.Name;
}
}
https://codereview.stackexchange.com/可能會感興趣的。 – mjwills
兩件事。你總是調用'ChangeKey',即使'_name == value'似乎是不必要的。其次,'FooItem'「知道」它的收藏,這不應該是它的責任。如何實現[INotifyPropertyChanged](https://stackoverflow.com/a/1316417/1336590)並讓集合爲其包含的每個對象註冊該事件,然後在任何引發該事件的對象時適當地調用'ChangeKey' 。 - 這樣,集合全權負責持有和維護對象,並且對象保持無視。 – Corak
嗨@Corak,偉大的提示,我闡述了它,它似乎很好。 – ilCosmico