dimanche 31 mars 2019

Convert IEnumerable to type that implements IEnumerable

GIVEN:

If you have the values:

  1. Type type
  2. IEnumerable enumerable

And the following conditions are met:

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

GENERAL QUESTION:

Is it possible to create an instance of type via reflection that contains all of the elements of enumerable?

BACKGROUND:

Most of the types in System.Collections have a constructor like Example(ICollection), and if type has a constructor like that it is simple and straightforward to do Activator.CreateInstance(type, enumerable). For types like Dictionary<TKey, TValue> though, it is not that simple. The only solution I have thought of looks like this:

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));
}

I would be more willing to accept this solution of KeyValuePair<TKey, TValue>implemented an interface which contained the properties Key and Value so you could say:

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

rather than relying on reflection to get the aforementioned property values.

This solution would only work for types within System.Collections or custom types that strongly adhere to the definitions of said types.

SPECIFIC QUESTION:

Is there a more elegant way of converting enumerable to the type of typethat also could account for edge cases like MyCollection : ICollection, where the type definition is not known to us?

UPDATE:

Here is an example:

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
}





Aucun commentaire:

Enregistrer un commentaire