-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNotifyShell.cs
More file actions
92 lines (75 loc) · 3.79 KB
/
Copy pathNotifyShell.cs
File metadata and controls
92 lines (75 loc) · 3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using System.Collections;
using System.Diagnostics;
namespace Kritjara.Collections;
/// <summary>Представляет коллекцию только для чтения с оповещением о добавлении/удалении элементов.</summary>
/// <typeparam name="T">Тип объектов, содержащихся в коллекции.</typeparam>
internal class NotifyShell<T> : NotifyBase<T>, IReadOnlyNotifyCollection<T>
{
private readonly Func<int> func_getcount;
private readonly Func<int, T> func_getitem;
private int ReadOnlyList_GetCount() => ((IReadOnlyList<T>)Items).Count;
private T ReadOnlyList_GetItem(int index) => ((IReadOnlyList<T>)Items)[index];
private int List_GetCount() => ((IList<T>)Items).Count;
private T List_GetItem(int index) => ((IList<T>)Items)[index];
private int ReadOnlyCollection_GetCount() => ((IReadOnlyCollection<T>)Items).Count;
private int Collection_GetCount() => ((ICollection<T>)Items).Count;
private T Enumerable_GetItem(int index) => ((IEnumerable<T>)Items).ElementAt(index);
/// <summary>
/// Основной источник элементов
/// </summary>
protected readonly INotify<T> Items;
/// <summary>
/// Инициализирует новый только для чтения экземпляр коллекции с оповещениями <see cref="INotify{T}"/>"/>
/// </summary>
/// <param name="items">Основной источник элементов</param>
public NotifyShell(INotify<T> items)
{
Debug.Assert(items is not INotifyCollection<T>);
if (items is IReadOnlyList<T>)
{
func_getcount = ReadOnlyList_GetCount;
func_getitem = ReadOnlyList_GetItem;
}
else if (items is IList<T>)
{
func_getcount = List_GetCount;
func_getitem = List_GetItem;
}
else if (items is IReadOnlyCollection<T>)
{
func_getcount = ReadOnlyCollection_GetCount;
func_getitem = Enumerable_GetItem;
}
else if (items is ICollection<T>)
{
func_getcount = Collection_GetCount;
func_getitem = Enumerable_GetItem;
}
else
{
throw new ArgumentException($"{nameof(items)} не является коллекцией элементов типа {typeof(T)}", nameof(items));
}
Items = items;
Items.ItemAdded += Source_ItemAdded;
Items.ItemRemoved += Source_ItemRemoved;
Items.RangeAdded += Source_RangeAdded;
Items.RangeRemoved += Items_RangeRemoved;
Items.ItemReplaced += Source_ItemReplaced;
Items.ItemMoved += Source_ItemMoved;
Items.CollectionCleared += Source_Cleared;
}
private void Source_ItemAdded(object sender, IItemAddedEventArgs<T> e) => RaiseItemAdded(e);
private void Source_ItemRemoved(object sender, IItemRemovedEventArgs<T> e) => RaiseItemRemoved(e);
private void Source_RangeAdded(object sender, IRangeAddedEventArgs<T> e) => RaiseRangeAdded(e);
private void Items_RangeRemoved(object sender, IRangeRemovedEventArgs<T> e) => RaiseRangeRemoved(e);
private void Source_ItemReplaced(object sender, IItemReplacedEventArgs<T> e) => RaiseItemReplaced(e);
private void Source_ItemMoved(object sender, IItemMovedEventArgs<T> e) => RaiseItemMoved(e);
private void Source_Cleared(object sender, ICollectionClearedEventArgs<T> e) => RaiseCollectionCleared(e);
/// <inheritdoc/>
public T this[int index] => func_getitem(index);
/// <inheritdoc/>
public int Count => func_getcount();
/// <inheritdoc/>
public IEnumerator<T> GetEnumerator() => ((IEnumerable<T>)Items).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}