1

I've googled for hours and also found various stackoverflow questions but none cater to my exact use-case. This is what I have: a method that takes 2 generic type parameters. The library is closed source so I cannot modify it. The method signature looks like:

 TTo Convert<TFrom, TTo>(TFrom obj)

However when you call this you always have to provide both type parameters, like this:

Convert<Dog, Cat>(dog);

I'm trying to support a use-case where only the destination type parameter is provided:

Convert<Cat>(dog);

So the method signature I need is as follows:

TTo Convert<TTo>(object obj){
     var TFrom = obj.GetType();
     Convert<TFrom, TTo>((TFrom)obj); // <--- throws an error right here
}

Can you help me fix this? This SO answer mentions using Lambda expression builders but I'm not sure how to do that in this use case. This SO answer mentions dynamic typing but its not what I need here.

Edit: The linked "duplicate" question comes close but it only handles dynamically casting generic types for regular method arguments, but doesn't handle TYPE arguments which is what I need.

Robin Rodricks
  • 110,798
  • 141
  • 398
  • 607
  • 2
    You have bigger problems than casting. You can't use `TFrom` as a generic type parameter, which makes this a possible duplicate of https://stackoverflow.com/questions/266115/pass-an-instantiated-system-type-as-a-type-parameter-for-a-generic-class – Sweeper Apr 13 '20 at 10:30
  • Does this answer your question? [Pass An Instantiated System.Type as a Type Parameter for a Generic Class](https://stackoverflow.com/questions/266115/pass-an-instantiated-system-type-as-a-type-parameter-for-a-generic-class) – Pavel Anikhouski Apr 13 '20 at 10:40

1 Answers1

3

This can be accomplished with Reflection. You just need to construct a method with your type parameters applied.

class Program
{

    public static TTo Convert<TFrom, TTo>(TFrom obj)
    {
        Console.WriteLine($"I was called with {obj}");
        return default;
    }

    public static TTo ConvertObject<TTo>(object obj)
    {
        var method = typeof(Program).GetMethod(nameof(Convert));
        var specialized = method.MakeGenericMethod(new[] { obj.GetType(), typeof(TTo) });
        return (TTo) specialized.Invoke(null, new[] { obj });
    }
}

Usage:

ConvertObject<int>(1.0f); //prints I was called with 1

The null is passed because the method was static; that should be substituted with the instance which contains the Convert method, as well as the type containing the method.

Asti
  • 12,447
  • 29
  • 38