如果Collection<T>
的类型T
仅在运行时知道(不在编译时),我想生成ImmutableList<T>
。
我想创建的方法可能像:
var immutableList = CreateImmutableList(originalList, type);
其中originalList为IEnumerable
,type为生成的T
的{{1}}。
如何?!
(我正在使用.NET .Core)
编辑:感谢评论,我找到了一个有效的解决方案。它使用AddRange方法。ImmutableList<T>
答案 0 :(得分:3)
您可以使用反射执行此操作:
Type
ImmutableList<T>
对象
这是一个展示的LINQPad程序。我假设“不可变列表”是指通过Nuget提供System.Collections.Immutable.ImmutableList<T>
:
void Main()
{
object il = CreateImmutableList(new[] { 1, 2, 3, 4, 5 }, typeof(int));
il.GetType().Dump();
il.Dump();
}
public static object CreateImmutableList(IEnumerable collection, Type elementType)
{
// TODO: guard clauses for parameters == null
var resultType = typeof(ImmutableList<>).MakeGenericType(elementType);
var result = resultType.GetField("Empty").GetValue(null);
var add = resultType.GetMethod("Add");
foreach (var element in collection)
result = add.Invoke(result, new object[] { element });
return result;
}
输出:
System.Collections.Immutable.ImmutableList`1[System.Int32]
1
2
3
4
5
答案 1 :(得分:0)
如果你准备好装箱/拆箱,那么你可以做这样的事情
var objectCollection = new Collection<object>();
objectCollection.Add(3);
objectCollection.Add(4);
var immutableList = objectCollection.ToImmutableList();
此处元素类型为int
,我们将值添加到对象集合中。如果我们想要取回键入的值,我们可以这样做:
foreach (var obj in immutableList)
{
int myVal = (int) Convert.ChangeType(obj, typeof(int));
Console.WriteLine(myVal);
}
注意:如果您的列表很大且元素类型是拥有装箱/拆箱的值类型,则可能会对性能产生影响
答案 2 :(得分:0)
您可以使用 CreateRange
。要尽量减少反射,请使用辅助方法:
private static ImmutableList<T> CreateImmutableList<T>(IEnumerable<object> source)
=> ImmutableList.CreateRange(source.Cast<T>());
private MethodInfo _createImmutableList = typeof(ReflectionExtensions)
.GetMethod(nameof(CreateImmutableList), BindingFlags.NonPublic | BindingFlags.Static);
// then:
return _createImmutableList
.MakeGenericMethod(elementType)
.Invoke(null, new object [] { collection });