【问题标题】:Convert IEnumerable to type that implements IEnumerable将 IEnumerable 转换为实现 IEnumerable 的类型
【发布时间】:2019-04-01 01:49:52
【问题描述】:

鉴于:

如果你有价值观:

  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
}

【问题讨论】:

  • 字典大小写中的可枚举是什么?
  • 它将是 IEnumerable>。我想我明白你在说什么,所以为了进一步澄清, enumerable 不是一个 Dictionary 已被强制转换为 IEnumerable。
  • 我没有在文档中看到它,并且手动创建一个 KeyValuePair 的数组并将其传递给 Dictionary 的构造函数会出现编译错误。 docs.microsoft.com/en-us/dotnet/api/…
  • “是否可以通过反射创建包含所有可枚举元素的类型实例?”是什么意思?
  • 我希望枚举时类型的实例等于可枚举。

标签: c# reflection collections


【解决方案1】:

这是使用旧 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

此技术允许您避免反射确定要创建和调用哪个泛型 MethodInfo 来创建数组。该框架会为您完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多