簡體   English   中英

將 IEnumerable 轉換為實現 IEnumerable 的類型

[英]Convert IEnumerable to type that implements IEnumerable

給定:

如果您有以下值:

  1. Type type
  2. IEnumerable enumerable

並且滿足以下條件:

  1. typeof(IEnumerable).IsAssignableFrom(type)
  2. enumerable.All(element => element.GetType() == type.GetElementType())

一般問題:

是否可以通過反射創建包含enumerable所有元素的type實例?

背景:

System.Collections大多數類型都有一個像Example(ICollection)這樣的構造函數,如果type有一個像這樣的構造函數,那么執行Activator.CreateInstance(type, enumerable)就很簡單了。 但是對於像Dictionary<TKey, TValue>這樣的類型,它並不是那么簡單。 我想到的唯一解決方案是這樣的:

var dictionary = (IDictionary) Activator.CreateInstance(type);
var elementType = enumerable.First().GetType();
var key = elementType.GetProperty("Key");
var value = elementType.GetProperty("Value");

foreach (var element in enumerable)
{
   dictionary.Add(key.GetValue(element), value.GetValue(element));
}

我更願意接受KeyValuePair<TKey, TValue>這個解決方案實現了一個包含屬性KeyValue的接口,所以你可以說:

var keyValuePair = (IKeyValuePair) element;
dictionary.Add(keyValuePair.Key, keyValuePair.Value);

而不是依靠反射來獲得上述屬性值。

此解決方案僅適用於System.Collections類型或強烈遵守所述類型定義的自定義類型。

具體問題:

是否有一種更優雅的方法可以將enumerable轉換為類型的type ,該類型也可以解釋像MyCollection : ICollection這樣的邊緣情況,其中我們不知道類型定義?

更新:

下面是一個例子:

var original = new Dictionary<int, string>
{
   //values
};

var type = original.GetType();
var enumerable = original.AsEnumerable();

var copy = (Dictionary<int, string>) DoSomeMagic(type, enumerable);

object DoSomeMagic(Type type, IEnumerable enumerable)
{
   //Add magic here
}

這是使用優質舊ArrayList的少數幾個原因之一。

System.Array ConvertUnknownIEnumerableToArray(IEnumerable ienumerable, Type type)
{
    var list = new ArrayList();
    foreach (var i in ienumerable) list.Add(i);
    return list.ToArray(type);
}

上面創建了一個強類型數組(命名array ),包含在任何可枚舉的名為ienumerable的具體對象中。 當然,數組實現ICollection

此技術允許您避免Reflection確定要創建和調用哪個通用MethodInfo來創建數組。 該框架為您做到了。

請求的解決方案應該能夠處理任何類型的容器,包括一個波紋管? 這似乎很難,不是說不可能。 填充此容器的唯一方法是通過Populate方法,但一般解決方案如何知道?

public class TupleList<T1, T2, T3> : IEnumerable<Tuple<T1, T2, T3>>
{
    private List<Tuple<T1, T2, T3>> _list = new List<Tuple<T1, T2, T3>>();

    public void Populate(T1 item1, T2 item2, T3 item3)
    {
        _list.Add(Tuple.Create(item1, item2, item3));
    }

    public Tuple<T1, T2, T3> this[int index] { get => _list[index]; }

    public IEnumerator<Tuple<T1, T2, T3>> GetEnumerator()
    {
        return _list.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM