创建在编译时未知的类型的ImmutableList

时间:2016-06-16 11:10:16

标签: c# .net immutability .net-core immutable-collections

如果Collection<T>的类型T仅在运行时知道(不在编译时),我想生成ImmutableList<T>

我想创建的方法可能像:

var immutableList = CreateImmutableList(originalList, type);

其中originalList为IEnumerable,type为生成的T的{​​{1}}。

如何?!

(我正在使用.NET .Core)

编辑:感谢评论,我找到了一个有效的解决方案。它使用AddRange方法。

ImmutableList<T>

3 个答案:

答案 0 :(得分:3)

您可以使用反射执行此操作:

  1. Type
  2. 创建正确的ImmutableList<T>对象
  3. 用数据填写
  4. 退货
  5. 这是一个展示的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 });