Kirk Woll
Kirk Woll

Reputation: 77616

Is there a better way to leverage an implicit type conversion operator on an `object` than using raw reflection?

Suppose you have a class Foo:

public class Foo
{
    public static implicit operator Foo(string s) 
    {
        return new Foo();
    }
}

If you try to leverage this operator in the usual way it works fine, of course:

var s = "foo";
Foo foo = s;

But what if you have the operand (s) but you only have it as an object:

object s = "foo";
Foo foo = s;

This fails for obvious reasons since there is no implicit conversion from object to Foo. However, the instance is a string and a type conversion operator does exist for this scenario. For the purpose of this question, assume that the variable in question (s) could be any of a number of types that might possibly have a type conversion operator defined to perform the requested conversion.

If you wanted, you could use reflection:

object s = "foo";
var converter = typeof(Foo)
    .GetMethods()
    .Single(x => 
        x.Name == "op_Implicit" && 
        x.ReturnType == typeof(Foo) && 
        x.GetParameters().Single().ParameterType == typeof(string));
Foo foo = (Foo)converter.Invoke(null, new[] { s });

I tried using Convert.ChangeType(s, typeof(Foo));, but this does not work. Is there any better alternative or is using reflection the best choice? (I'm unhappy with using reflection for the standard reasons -- it's probably not maximally performant and the appearance of the code is unseemly. But if it's the best bet, then fine.)

Upvotes: 0

Views: 65

Answers (1)

user743382
user743382

Reputation:

I'm unhappy with using reflection for the standard reasons -- it's probably not maximally performant

The required information is simply not available before run-time, so you cannot avoid determining that information at run-time. That means reflection.

You can optimise your reflection based on your usage: if you often require the exact same conversion, and you have few types that would need a conversion, you could create a Dictionary<Type, Func<object, Foo>>. Create a DynamicMethod for the specific type once, create a delegate, and call it over and over again. Or determine the method dynamically each time if the setting up of dynamic methods adds more time than it saves in your usage patterns.

and the appearance of the code is unseemly.

Then don't use reflection directly, use libraries that do the heavy work for you already. In this case, you should be able to use dynamic, which uses reflection behind the scenes.

Of course, libraries that hide away the reflection make it hard to optimise the reflection's performance. You'll have to hope that the implementer did a good enough job. But you can just measure that.

Upvotes: 2

Related Questions