Avoid dynamic in AddRange detection
This commit is contained in:
1 parent
976c5eb78b
commit
1d4d5e9217
2 files changed
+138
-28
No files matched your search
@@ -1,13 +1,74 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Recyclable.Collections
|
namespace Recyclable.Collections
|
||||||
{
|
{
|
||||||
public static class zRecyclableListAddRange
|
public static class zRecyclableListAddRange
|
||||||
{
|
{
|
||||||
private static void AddRangeEnumerated<T>(this RecyclableList<T> list, IEnumerable<T> items, int growByCount)
|
private static class AddRangeHelper<T>
|
||||||
{
|
{
|
||||||
|
internal static readonly Type? DictionaryType;
|
||||||
|
internal static readonly Type? SortedListType;
|
||||||
|
internal static readonly Action<RecyclableList<T>, IEnumerable<T>>? DictionaryAdder;
|
||||||
|
internal static readonly Action<RecyclableList<T>, IEnumerable<T>>? SortedListAdder;
|
||||||
|
|
||||||
|
static AddRangeHelper()
|
||||||
|
{
|
||||||
|
var itemType = typeof(T);
|
||||||
|
if (itemType.IsGenericType)
|
||||||
|
{
|
||||||
|
var genericDefinition = itemType.GetGenericTypeDefinition();
|
||||||
|
if (genericDefinition == typeof(KeyValuePair<,>))
|
||||||
|
{
|
||||||
|
var args = itemType.GetGenericArguments();
|
||||||
|
DictionaryType = typeof(RecyclableDictionary<,>).MakeGenericType(args);
|
||||||
|
|
||||||
|
var listType = typeof(RecyclableList<>).MakeGenericType(itemType);
|
||||||
|
var method = typeof(zRecyclableListAddRange).GetMethod(
|
||||||
|
nameof(AddRange),
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Static,
|
||||||
|
null,
|
||||||
|
new[] { listType, DictionaryType },
|
||||||
|
null)!.MakeGenericMethod(args);
|
||||||
|
|
||||||
|
var listParam = Expression.Parameter(typeof(RecyclableList<T>), "list");
|
||||||
|
var itemsParam = Expression.Parameter(typeof(IEnumerable<T>), "items");
|
||||||
|
var call = Expression.Call(method,
|
||||||
|
Expression.Convert(listParam, listType),
|
||||||
|
Expression.Convert(itemsParam, DictionaryType));
|
||||||
|
|
||||||
|
DictionaryAdder = Expression.Lambda<Action<RecyclableList<T>, IEnumerable<T>>>(call, listParam, itemsParam).Compile();
|
||||||
|
}
|
||||||
|
else if (genericDefinition == typeof(ValueTuple<,>))
|
||||||
|
{
|
||||||
|
var args = itemType.GetGenericArguments();
|
||||||
|
SortedListType = typeof(RecyclableSortedList<,>).MakeGenericType(args);
|
||||||
|
|
||||||
|
var listType = typeof(RecyclableList<>).MakeGenericType(itemType);
|
||||||
|
var method = typeof(zRecyclableListAddRange).GetMethod(
|
||||||
|
nameof(AddRange),
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Static,
|
||||||
|
null,
|
||||||
|
new[] { listType, SortedListType },
|
||||||
|
null)!.MakeGenericMethod(args);
|
||||||
|
|
||||||
|
var listParam = Expression.Parameter(typeof(RecyclableList<T>), "list");
|
||||||
|
var itemsParam = Expression.Parameter(typeof(IEnumerable<T>), "items");
|
||||||
|
var call = Expression.Call(method,
|
||||||
|
Expression.Convert(listParam, listType),
|
||||||
|
Expression.Convert(itemsParam, SortedListType));
|
||||||
|
|
||||||
|
SortedListAdder = Expression.Lambda<Action<RecyclableList<T>, IEnumerable<T>>>(call, listParam, itemsParam).Compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddRangeEnumerated<T>(this RecyclableList<T> list, IEnumerable<T> items, int growByCount)
|
||||||
|
{
|
||||||
var enumerator = items.GetEnumerator();
|
var enumerator = items.GetEnumerator();
|
||||||
if (!enumerator.MoveNext())
|
if (!enumerator.MoveNext())
|
||||||
{
|
{
|
||||||
@@ -577,19 +638,13 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
AddRange(list, sourceQueue);
|
AddRange(list, sourceQueue);
|
||||||
}
|
}
|
||||||
else if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(KeyValuePair<,>)
|
else if (AddRangeHelper<T>.DictionaryAdder != null && AddRangeHelper<T>.DictionaryType!.IsInstanceOfType(items))
|
||||||
&& items.GetType().IsGenericType && items.GetType().GetGenericTypeDefinition() == typeof(RecyclableDictionary<,>))
|
|
||||||
{
|
{
|
||||||
dynamic dynList = list;
|
AddRangeHelper<T>.DictionaryAdder!(list, items);
|
||||||
dynamic dynDict = items;
|
|
||||||
AddRange(dynList, dynDict);
|
|
||||||
}
|
}
|
||||||
else if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(ValueTuple<,>)
|
else if (AddRangeHelper<T>.SortedListAdder != null && AddRangeHelper<T>.SortedListType!.IsInstanceOfType(items))
|
||||||
&& items.GetType().IsGenericType && items.GetType().GetGenericTypeDefinition() == typeof(RecyclableSortedList<,>))
|
|
||||||
{
|
{
|
||||||
dynamic dynList = list;
|
AddRangeHelper<T>.SortedListAdder!(list, items);
|
||||||
dynamic dynSortedList = items;
|
|
||||||
AddRange(dynList, dynSortedList);
|
|
||||||
}
|
}
|
||||||
else if (items is IReadOnlyList<T> sourceIReadOnlyList)
|
else if (items is IReadOnlyList<T> sourceIReadOnlyList)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,14 +1,75 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
using Recyclable.Collections.Pools;
|
using Recyclable.Collections.Pools;
|
||||||
|
|
||||||
namespace Recyclable.Collections
|
namespace Recyclable.Collections
|
||||||
{
|
{
|
||||||
public static class zRecyclableLongListAddRange
|
public static class zRecyclableLongListAddRange
|
||||||
{
|
{
|
||||||
private static void AddRangeEnumerated<T>(this RecyclableLongList<T> targetList, IEnumerable<T> items)
|
private static class AddRangeHelper<T>
|
||||||
{
|
{
|
||||||
|
internal static readonly Type? DictionaryType;
|
||||||
|
internal static readonly Type? SortedListType;
|
||||||
|
internal static readonly Action<RecyclableLongList<T>, IEnumerable<T>>? DictionaryAdder;
|
||||||
|
internal static readonly Action<RecyclableLongList<T>, IEnumerable<T>>? SortedListAdder;
|
||||||
|
|
||||||
|
static AddRangeHelper()
|
||||||
|
{
|
||||||
|
var itemType = typeof(T);
|
||||||
|
if (itemType.IsGenericType)
|
||||||
|
{
|
||||||
|
var genericDefinition = itemType.GetGenericTypeDefinition();
|
||||||
|
if (genericDefinition == typeof(KeyValuePair<,>))
|
||||||
|
{
|
||||||
|
var args = itemType.GetGenericArguments();
|
||||||
|
DictionaryType = typeof(RecyclableDictionary<,>).MakeGenericType(args);
|
||||||
|
|
||||||
|
var listType = typeof(RecyclableLongList<>).MakeGenericType(itemType);
|
||||||
|
var method = typeof(zRecyclableLongListAddRange).GetMethod(
|
||||||
|
nameof(AddRange),
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Static,
|
||||||
|
null,
|
||||||
|
new[] { listType, DictionaryType },
|
||||||
|
null)!.MakeGenericMethod(args);
|
||||||
|
|
||||||
|
var listParam = Expression.Parameter(typeof(RecyclableLongList<T>), "list");
|
||||||
|
var itemsParam = Expression.Parameter(typeof(IEnumerable<T>), "items");
|
||||||
|
var call = Expression.Call(method,
|
||||||
|
Expression.Convert(listParam, listType),
|
||||||
|
Expression.Convert(itemsParam, DictionaryType));
|
||||||
|
|
||||||
|
DictionaryAdder = Expression.Lambda<Action<RecyclableLongList<T>, IEnumerable<T>>>(call, listParam, itemsParam).Compile();
|
||||||
|
}
|
||||||
|
else if (genericDefinition == typeof(ValueTuple<,>))
|
||||||
|
{
|
||||||
|
var args = itemType.GetGenericArguments();
|
||||||
|
SortedListType = typeof(RecyclableSortedList<,>).MakeGenericType(args);
|
||||||
|
|
||||||
|
var listType = typeof(RecyclableLongList<>).MakeGenericType(itemType);
|
||||||
|
var method = typeof(zRecyclableLongListAddRange).GetMethod(
|
||||||
|
nameof(AddRange),
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Static,
|
||||||
|
null,
|
||||||
|
new[] { listType, SortedListType },
|
||||||
|
null)!.MakeGenericMethod(args);
|
||||||
|
|
||||||
|
var listParam = Expression.Parameter(typeof(RecyclableLongList<T>), "list");
|
||||||
|
var itemsParam = Expression.Parameter(typeof(IEnumerable<T>), "items");
|
||||||
|
var call = Expression.Call(method,
|
||||||
|
Expression.Convert(listParam, listType),
|
||||||
|
Expression.Convert(itemsParam, SortedListType));
|
||||||
|
|
||||||
|
SortedListAdder = Expression.Lambda<Action<RecyclableLongList<T>, IEnumerable<T>>>(call, listParam, itemsParam).Compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddRangeEnumerated<T>(this RecyclableLongList<T> targetList, IEnumerable<T> items)
|
||||||
|
{
|
||||||
using IEnumerator<T> enumerator = items.GetEnumerator();
|
using IEnumerator<T> enumerator = items.GetEnumerator();
|
||||||
if (!enumerator.MoveNext())
|
if (!enumerator.MoveNext())
|
||||||
{
|
{
|
||||||
@@ -438,18 +499,12 @@ namespace Recyclable.Collections
|
|||||||
targetList.AddRange(sourceQueue);
|
targetList.AddRange(sourceQueue);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case var _ when typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(KeyValuePair<,>)
|
case var _ when AddRangeHelper<T>.DictionaryAdder != null && AddRangeHelper<T>.DictionaryType!.IsInstanceOfType(items):
|
||||||
&& items.GetType().IsGenericType && items.GetType().GetGenericTypeDefinition() == typeof(RecyclableDictionary<,>):
|
AddRangeHelper<T>.DictionaryAdder!(targetList, items);
|
||||||
dynamic dynTargetList = targetList;
|
|
||||||
dynamic dynDict = items;
|
|
||||||
AddRange(dynTargetList, dynDict);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case var _ when typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(ValueTuple<,>)
|
case var _ when AddRangeHelper<T>.SortedListAdder != null && AddRangeHelper<T>.SortedListType!.IsInstanceOfType(items):
|
||||||
&& items.GetType().IsGenericType && items.GetType().GetGenericTypeDefinition() == typeof(RecyclableSortedList<,>):
|
AddRangeHelper<T>.SortedListAdder!(targetList, items);
|
||||||
dynamic dynTargetList2 = targetList;
|
|
||||||
dynamic dynSortedList = items;
|
|
||||||
AddRange(dynTargetList2, dynSortedList);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in new issue
Block a user