netstandard2.0;2.1;net5.0
This commit is contained in:
parent
81be2a3e18
commit
cfaefc4454
@ -4,4 +4,8 @@
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\ObservableCollections\ObservableCollections.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,7 +1,12 @@
|
||||
@page "/"
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
<button @onclick=OnClick>button</button>
|
||||
|
||||
Welcome to your new app.
|
||||
|
||||
<SurveyPrompt Title="How is Blazor working for you?" />
|
||||
<table>
|
||||
@foreach (var item in ItemsView)
|
||||
{
|
||||
<tr>
|
||||
<td>@item</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
@ -1,9 +1,40 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using ObservableCollections;
|
||||
|
||||
namespace BlazorApp.Pages;
|
||||
|
||||
public partial class Index
|
||||
{
|
||||
ObservableList<int> list;
|
||||
public ISynchronizedView<int, int> ItemsView { get; set; }
|
||||
int adder = 99;
|
||||
|
||||
|
||||
RenderFragment fragment;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
list = new ObservableList<int>();
|
||||
list.AddRange(new[] { 1, 10, 188 });
|
||||
ItemsView = list.CreateSortedView(x => x, x => x, comparer: Comparer<int>.Default).WithINotifyCollectionChanged();
|
||||
|
||||
|
||||
fragment = builder =>
|
||||
{
|
||||
builder.GetFrames();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OnClick()
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(_ =>
|
||||
{
|
||||
list.Add(adder++);
|
||||
|
||||
_ = InvokeAsync(StateHasChanged);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace WpfApp
|
||||
InitializeComponent();
|
||||
this.DataContext = this;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
list = new ObservableList<int>();
|
||||
|
@ -1,4 +1,6 @@
|
||||
using ObservableCollections.Internal;
|
||||
#nullable disable
|
||||
|
||||
using ObservableCollections.Internal;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
@ -1,4 +1,6 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
using System.Buffers;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace ObservableCollections.Internal
|
||||
@ -24,7 +26,7 @@ namespace ObservableCollections.Internal
|
||||
|
||||
public CloneCollection(IEnumerable<T> source)
|
||||
{
|
||||
if (Enumerable.TryGetNonEnumeratedCount(source, out var count))
|
||||
if (source.TryGetNonEnumeratedCount(out var count))
|
||||
{
|
||||
var array = ArrayPool<T>.Shared.Rent(count);
|
||||
|
||||
@ -70,7 +72,7 @@ namespace ObservableCollections.Internal
|
||||
{
|
||||
if (array.Length == index)
|
||||
{
|
||||
ArrayPool<T>.Shared.Return(array, RuntimeHelpers.IsReferenceOrContainsReferences<T>());
|
||||
ArrayPool<T>.Shared.Return(array, RuntimeHelpersEx.IsReferenceOrContainsReferences<T>());
|
||||
}
|
||||
array = ArrayPool<T>.Shared.Rent(index * 2);
|
||||
}
|
||||
@ -79,7 +81,7 @@ namespace ObservableCollections.Internal
|
||||
{
|
||||
if (array != null)
|
||||
{
|
||||
ArrayPool<T>.Shared.Return(array, RuntimeHelpers.IsReferenceOrContainsReferences<T>());
|
||||
ArrayPool<T>.Shared.Return(array, RuntimeHelpersEx.IsReferenceOrContainsReferences<T>());
|
||||
array = null;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Buffers;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
@ -32,7 +33,7 @@ namespace ObservableCollections.Internal
|
||||
void EnsureCapacity()
|
||||
{
|
||||
var newArray = array.AsSpan().ToArray();
|
||||
ArrayPool<T>.Shared.Return(array!, RuntimeHelpers.IsReferenceOrContainsReferences<T>());
|
||||
ArrayPool<T>.Shared.Return(array!, RuntimeHelpersEx.IsReferenceOrContainsReferences<T>());
|
||||
array = newArray;
|
||||
}
|
||||
|
||||
@ -40,7 +41,7 @@ namespace ObservableCollections.Internal
|
||||
{
|
||||
if (array != null)
|
||||
{
|
||||
ArrayPool<T>.Shared.Return(array, RuntimeHelpers.IsReferenceOrContainsReferences<T>());
|
||||
ArrayPool<T>.Shared.Return(array, RuntimeHelpersEx.IsReferenceOrContainsReferences<T>());
|
||||
array = null;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
namespace ObservableCollections.Internal
|
||||
{
|
||||
|
@ -1,5 +1,8 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
namespace ObservableCollections.Internal
|
||||
{
|
||||
|
@ -1,8 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFrameworks>netstandard2.0;netstandard2.1;net5.0;net6.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="$(TargetFramework) == 'netstandard2.0'">
|
||||
<PackageReference Include="System.Memory" Version="4.5.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,6 +1,9 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
namespace ObservableCollections
|
||||
{
|
||||
|
@ -20,7 +20,15 @@ namespace ObservableCollections
|
||||
|
||||
public ObservableDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection)
|
||||
{
|
||||
#if NET6_0_OR_GREATER
|
||||
this.dictionary = new Dictionary<TKey, TValue>(collection);
|
||||
#else
|
||||
this.dictionary = new Dictionary<TKey, TValue>();
|
||||
foreach (var item in collection)
|
||||
{
|
||||
dictionary.Add(item.Key, item.Value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public event NotifyCollectionChangedEventHandler<KeyValuePair<TKey, TValue>>? CollectionChanged;
|
||||
@ -191,7 +199,9 @@ namespace ObservableCollections
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CS8767
|
||||
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
|
||||
#pragma warning restore CS8767
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ObservableCollections
|
||||
{
|
||||
|
@ -1,6 +1,9 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace ObservableCollections
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ObservableCollections
|
||||
@ -16,11 +18,15 @@ namespace ObservableCollections
|
||||
this.set = new HashSet<T>();
|
||||
}
|
||||
|
||||
#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
|
||||
|
||||
public ObservableHashSet(int capacity)
|
||||
{
|
||||
this.set = new HashSet<T>(capacity);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public ObservableHashSet(IEnumerable<T> collection)
|
||||
{
|
||||
this.set = new HashSet<T>(collection);
|
||||
@ -174,11 +180,15 @@ namespace ObservableCollections
|
||||
}
|
||||
}
|
||||
|
||||
#if !NETSTANDARD2_0
|
||||
|
||||
public bool TryGetValue(T equalValue, [MaybeNullWhen(false)] out T actualValue)
|
||||
{
|
||||
return set.TryGetValue(equalValue, out actualValue);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
|
@ -1,6 +1,9 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
namespace ObservableCollections
|
||||
{
|
||||
|
@ -102,7 +102,6 @@ namespace ObservableCollections
|
||||
lock (SyncRoot)
|
||||
{
|
||||
var index = list.Count;
|
||||
list.EnsureCapacity(items.Length);
|
||||
foreach (var item in items)
|
||||
{
|
||||
list.Add(item);
|
||||
@ -242,7 +241,11 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
#if NET5_0_OR_GREATER
|
||||
var range = CollectionsMarshal.AsSpan(list).Slice(index, count);
|
||||
#else
|
||||
var range = list.GetRange(index, count);
|
||||
#endif
|
||||
|
||||
// require copy before remove
|
||||
using (var xs = new CloneCollection<T>(range))
|
||||
|
@ -1,6 +1,9 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ObservableCollections
|
||||
{
|
||||
@ -120,7 +123,6 @@ namespace ObservableCollections
|
||||
}
|
||||
else
|
||||
{
|
||||
queue.EnsureCapacity(e.NewItems.Length);
|
||||
foreach (var item in e.NewItems)
|
||||
{
|
||||
var v = (item, selector(item));
|
||||
|
@ -3,6 +3,10 @@ using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
namespace ObservableCollections
|
||||
{
|
||||
@ -105,11 +109,13 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
if (queue.TryDequeue(out result))
|
||||
if (queue.Count != 0)
|
||||
{
|
||||
result = queue.Dequeue();
|
||||
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Remove(result, 0));
|
||||
return true;
|
||||
}
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -130,7 +136,7 @@ namespace ObservableCollections
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<T>.Shared.Return(dest, RuntimeHelpers.IsReferenceOrContainsReferences<T>());
|
||||
ArrayPool<T>.Shared.Return(dest, RuntimeHelpersEx.IsReferenceOrContainsReferences<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,7 +175,13 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return queue.TryPeek(out result);
|
||||
if (queue.Count != 0)
|
||||
{
|
||||
result = queue.Peek();
|
||||
return true;
|
||||
}
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,14 +201,6 @@ namespace ObservableCollections
|
||||
}
|
||||
}
|
||||
|
||||
public void EnsureCapacity(int capacity)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
queue.EnsureCapacity(capacity);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return new SynchronizedEnumerator<T>(SyncRoot, queue.GetEnumerator());
|
||||
|
@ -1,6 +1,9 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
namespace ObservableCollections
|
||||
{
|
||||
|
@ -1,4 +1,7 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
|
||||
namespace ObservableCollections
|
||||
|
@ -1,6 +1,9 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
namespace ObservableCollections
|
||||
{
|
||||
@ -120,7 +123,6 @@ namespace ObservableCollections
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.EnsureCapacity(e.NewItems.Length);
|
||||
foreach (var item in e.NewItems)
|
||||
{
|
||||
var v = (item, selector(item));
|
||||
|
@ -1,6 +1,8 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
@ -102,11 +104,14 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
if (stack.TryPop(out result))
|
||||
if (stack.Count != 0)
|
||||
{
|
||||
result = stack.Pop();
|
||||
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Remove(result, 0));
|
||||
return true;
|
||||
}
|
||||
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -127,7 +132,7 @@ namespace ObservableCollections
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<T>.Shared.Return(dest, RuntimeHelpers.IsReferenceOrContainsReferences<T>());
|
||||
ArrayPool<T>.Shared.Return(dest, RuntimeHelpersEx.IsReferenceOrContainsReferences<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,7 +171,13 @@ namespace ObservableCollections
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return stack.TryPeek(out result);
|
||||
if (stack.Count != 0)
|
||||
{
|
||||
result = stack.Peek();
|
||||
return true;
|
||||
}
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,14 +197,6 @@ namespace ObservableCollections
|
||||
}
|
||||
}
|
||||
|
||||
public void EnsureCapacity(int capacity)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
stack.EnsureCapacity(capacity);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return new SynchronizedEnumerator<T>(SyncRoot, stack.GetEnumerator());
|
||||
|
@ -1,4 +1,6 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ObservableCollections
|
||||
@ -147,7 +149,7 @@ namespace ObservableCollections
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Array.Clear(buffer);
|
||||
Array.Clear(buffer, 0, buffer.Length);
|
||||
head = 0;
|
||||
count = 0;
|
||||
}
|
||||
|
64
src/ObservableCollections/Shims/Collections.cs
Normal file
64
src/ObservableCollections/Shims/Collections.cs
Normal file
@ -0,0 +1,64 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
internal static class CollectionExtensions
|
||||
{
|
||||
public static void Deconstruct<TKey, TValue>(this KeyValuePair<TKey, TValue> kvp, out TKey key, out TValue value)
|
||||
{
|
||||
key = kvp.Key;
|
||||
value = kvp.Value;
|
||||
}
|
||||
|
||||
public static bool Remove<TKey, TValue>(this SortedDictionary<TKey, TValue> dict, TKey key, out TValue value)
|
||||
{
|
||||
if (dict.TryGetValue(key, out value))
|
||||
{
|
||||
return dict.Remove(key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool Remove<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, out TValue value)
|
||||
{
|
||||
if (dict.TryGetValue(key, out value))
|
||||
{
|
||||
return dict.Remove(key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !NET6_0_OR_GREATER
|
||||
|
||||
public static bool TryGetNonEnumeratedCount<T>(this IEnumerable<T> source, out int count)
|
||||
{
|
||||
if (source is ICollection<T> collection)
|
||||
{
|
||||
count = collection.Count;
|
||||
return true;
|
||||
}
|
||||
if (source is IReadOnlyCollection<T> rCollection)
|
||||
{
|
||||
count = rCollection.Count;
|
||||
return true;
|
||||
}
|
||||
count = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !NET5_0_OR_GREATER
|
||||
|
||||
internal interface IReadOnlySet<T> : System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
18
src/ObservableCollections/Shims/CompilerServices.cs
Normal file
18
src/ObservableCollections/Shims/CompilerServices.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
internal static class RuntimeHelpersEx
|
||||
{
|
||||
internal static bool IsReferenceOrContainsReferences<T>()
|
||||
{
|
||||
#if NETSTANDARD2_0
|
||||
return true;
|
||||
#else
|
||||
return RuntimeHelpers.IsReferenceOrContainsReferences<T>();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
24
src/ObservableCollections/Shims/Nullables.cs
Normal file
24
src/ObservableCollections/Shims/Nullables.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
internal sealed class MaybeNullWhenAttribute : Attribute
|
||||
{
|
||||
public MaybeNullWhenAttribute(bool returnValue)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class DoesNotReturnAttribute : Attribute
|
||||
{
|
||||
public DoesNotReturnAttribute()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user