ДАНА:
Если у вас есть значения:
Type type
IEnumerable enumerable
И выполняются следующие условия:
typeof(IEnumerable).IsAssignableFrom(type)
enumerable.All(element => element.GetType() == type.GetElementType())
ОБЩИЙ ВОПРОС:
Можно ли с помощью отражения создать экземпляр type
, который содержит все элементы enumerable
?
ФОН:
Mostиз типов в 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>
реализовал интерфейс, который содержал свойства Key
и Value
, чтобы вы моглискажем:
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
}