mercredi 13 novembre 2019

Populate an arbitrary concrete IEnumerable, from another IEnumerable

I'm writing some reflection code. Ah well.


I have an IEnumerable<TData> values object, and an Expression<Func<TInstance, IEnumerable<TData>>> representing a property whose type implements (but is not declared as) IEnumerable<TData>.

e.g. I have a property declared as: public SomeProp List<String> {get;set;}, a values object new[] {"a", "bee", "sea"}, and the expression obj => obj.SomeProp

I have successfully written the code that extracts the information:

the concrete implementation of IEnumerable<> for SomeProp is List<>

and thus I can call values.ToList() on my IEnumerable<string> values object and successfully assign the result to the property.

For any particular implementation of IEnumerable<> I could manually write code to detect that implementation, and code to create a concrete object that satisfies it. Indeed I currently have a small mapping dictionary, which covers some cases:

new Dictionary<Type, Func<IEnumerable<TProp>, IEnumerable<TProp>>>
{
    { typeof(List<>), (vals) => vals.ToList() },
    { typeof(IList<>), (vals) => vals.ToList() },
    { typeof(Collection<>), (vals) => new Collection<TProp>(vals.ToList()) },
    { typeof(ICollection<>), (vals) => new Collection<TProp>(vals.ToList()) },
};

Naturally, that doesn't even cover most of the common cases, let alone covering every possible case!


Is there any way to write reflection code that will take an arbitrary "values" IEnumerable<T>, and a target concrete IEnumerable<T>, and create that concrete instance from the values?

It seems a little optimistic, but I figured it was worth asking :)





Aucun commentaire:

Enregistrer un commentaire