vendredi 9 avril 2021

Cast to Type with reflection without generic argument

I have an issue which involves casting to different Types

I have a class which is a wrapper, which contains an inner wrapper which contains T here is the structure:

public class Wrapper
{
    public readonly Guid Foo;

    public Wrapper(Guid foo)
    {
        Foo = foo;
    }
}

public class Wrapper<T> : Wrapper
{
    public readonly InnerWrapper<T> InnerWrapper;

    public Wrapper(Guid foo, InnerWrapper<T> innerWrapper) 
        : base(foo)
    {
        InnerWrapper = innerWrapper;
    }
}

public class InnerWrapper<T> 
{
    public readonly Guid Bar;
    public readonly T Content;
    public InnerWrapper(T content, Guid bar)
    {
        Content = content;
        Bar = bar;
    }
}

In another part of the code I have a List<Wrapper>. notice that is a list of wrapper not a list of wrapper<T> which means that T can be any class. when this translates is expected to have something like

{
    wrapper<Class1>,
    wrapper<Class2>
}

and so on.

At some point in the code there is a "helper class" which contains the object as object type and the Type

public class Helper
{
    public readonly object Obj;
    public readonly Type Type;

    public Helper(object obj, Type type)
    {
        Obj = obj;
        Type = type;
    }
}

And here is where my problem begins, I created a helper method to convert from List<Helper> to List<Wrapper> and it does it, but the inner object is type object instead of being the actual type.

And i have no clue of how to convert from object to the actual type without using generics, and as T can be multiples types I cannot use them.

This is the helper classs

public static class HelperExtensions
{
    public static T CastTo<T>(this object o) => (T)o;

    public static List<Wrapper> ToWrapper(this IEnumerable<Helper> helperList)
    {
        List<Wrapper> wrapperResponseList = new List<Wrapper>();
        foreach (var help in helperList)
        {
            // doesn't work either var typedValue = Convert.ChangeType(help.Obj, help.Type);

            var methodInfo = typeof(HelperExtensions).GetMethod(nameof(CastTo), BindingFlags.Static | BindingFlags.Public);
            var genericArguments = new[] { help.Type };
            var genericMethodInfo = methodInfo?.MakeGenericMethod(genericArguments);
            var typedValue = genericMethodInfo?.Invoke(null, new[] { help.Obj });

            var wrapper = typedValue.BuildWrapper(Guid.NewGuid(), Guid.NewGuid());

            wrapperResponseList.Add(wrapper);
        }

        return wrapperResponseList;
    }


    //This one called individually does the work properly
    public static Wrapper<T> BuildWrapper<T>(this T obj, Guid foo, Guid bar)
    {
        InnerWrapper<T> inner = new InnerWrapper<T>(obj, bar);
        return new Wrapper<T>(foo, inner);
    }

}

to show the code here I also Created a test class

public class Placeholder
{
    public Guid Value { get; }

    public Placeholder(Guid value)
    {
        Value = value;
    }
}

so when I call

Placeholder placeholder = new Placeholder(Guid.NewGuid());
Helper helper1 = new Helper(placeholder, placeholder.GetType());
var result = new List<Helper> { helper1 }.ToWrapper();

It generates a List<Wrapper> but instead of wrapper<T> it is generating Wrapper<Object>

Any idea how can I cast it properly?

I also created a fiddle https://dotnetfiddle.net/pz3JDz which contains all the needed code to test.

Thanks In advance for your help.





Aucun commentaire:

Enregistrer un commentaire