【发布时间】:2016-06-16 11:10:15
【问题描述】:
给定一个 Collection<T> 其类型 T 仅在运行时(而不是在编译时)已知,我想生成一个 ImmutableList<T>。
我想创建的方法可能是这样的:
var immutableList = CreateImmutableList(originalList, type);
其中 originalList 是 IEnumerable,type 是生成的 ImmutableList<T> 的 T。
怎么样?!
(我正在使用 NET .Core)
编辑:感谢 cmets,我找到了一个可行的解决方案。它使用 AddRange 方法。
namespace Sample.Tests
{
using System;
using System.Collections;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using Xunit;
public class ImmutabilityTests
{
[Fact]
public void CollectionCanBeConvertedToImmutable()
{
var original = new Collection<object>() { 1, 2, 3, 4, };
var result = original.AsImmutable(typeof(int));
Assert.NotEmpty(result);
Assert.IsAssignableFrom<ImmutableList<int>>(result);
}
}
public static class ReflectionExtensions
{
public static IEnumerable AsImmutable(this IEnumerable collection, Type elementType)
{
var immutableType = typeof(ImmutableList<>).MakeGenericType(elementType);
var addRangeMethod = immutableType.GetMethod("AddRange");
var typedCollection = ToTyped(collection, elementType);
var emptyImmutableList = immutableType.GetField("Empty").GetValue(null);
emptyImmutableList = addRangeMethod.Invoke(emptyImmutableList, new[] { typedCollection });
return (IEnumerable)emptyImmutableList;
}
private static object ToTyped(IEnumerable original, Type type)
{
var method = typeof(Enumerable).GetMethod("Cast", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(type);
return method.Invoke(original, new object[] { original });
}
}
}
【问题讨论】:
-
这行不通。要么您在编译时知道类型,这使得创建
Collection<MyType>变得容易,要么您不知道类型,在这种情况下您不能指望编译器猜测您在运行时提供的内容。 -
CreateImmutableList必须返回object,因为它不能返回ImmutableList<T>(毕竟,我们不知道T)。那是你要的吗?在这种情况下,请明确说明var应该是什么类型。 -
originalList在运行时也是IEnumerable<T>吗? -
另外,你说的是
System.Collections.Immutable.ImmutableList<T>吗? -
是的!那!不可变列表
标签: c# .net immutability .net-core immutable-collections