lundi 27 février 2017

Generic collection transformation with reflection

I am using .Net Core and have the following problems:

I want to use reflection to transform the properties of an object and store the results in a new copy of that object. This works great for non-collections and arrays, but i am facing problems with generic collections (ICollection<T>).

There are two problems:

1.) How to ensure that the runtime type is of type ICollection<any T>. I was able to achieve this for ICollection, but how to check if an object implements the generic interface?

I'd like to do something like this:

public object Transform(object objectToTransform) {
    var type = objectToTransform.GetType();
    var obj = Activator.CreateInstance(type);
    foreach (var propertyInfo in type.GetRuntimeProperties()) {
        ...
        if(typeof(ICollection<???>).GetTypeInfo().IsAssignableFrom(propertyInfo.PropertyType.GetTypeInfo())) {
            // transform all items and store them in a new collection of the same runtime type
        }
        ...
    }
    return obj;
}

I Tried typeof(ICollection<>) but that does not work. typeof(ICollection) is not an option for me, since i need to ensure that the target collection has the Add Method of ICollection<T>.

2.) The second problem is about the transformation step.

I tried to use dynamic to ignore static types for the part which adds the transformed items to the new collection:

var collection = (IEnumerable)propertyInfo.GetMethod.Invoke(objectToTransform, null);
dynamic x = Activator.CreateInstance(collection.GetType());
foreach (var item in collection) {
    x.Add(Transform(item)); // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
}

The call of the Add method on the dynamic object "x" throws the following exception: "Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: The best overloaded match for System.Collections.Generic.List<SomeType>.Add(SomeType) has some invalid arguments."

I'm aware that the Add method isn't implemented for all ICollection<T> like ReadonlyCollections. Currently i just want to know if and how this dynamic call works.

I know that dynamic is unsafe and looks like a hack, but i havent found another solution yet, which does not involve a transformation for each implementation of the collection interfaces.





Aucun commentaire:

Enregistrer un commentaire