Isaiah Lee
Isaiah Lee

Reputation: 448

Invoke a Func object using reflection and a Type that's known at runtime

I've been trying to wrap my head around handling this scenario. The various similar (but not specifically the same) questions I've browsed on SO hasn't quite led me to where I'd like.

I have a situation where I have a Type and an object of type Func<string, (bool, T)> where T matches the Type. I'd like to be able to, via reflection or other means, call its Invoke method.

I have some Type at runtime:

Type type;

I have the Func in memory, but as an object:

object func;

The underlying Type of func is what I described earlier. For example, if type represents DateTime, then func's underlying type would be:

Func<string, (bool, DateTime)>

But type can be anything at runtime, so if it was instead an int, then func would now be a

Func<string, (bool, int)>

How can I use the fact that I have the correct type at runtime, to invoke my func? I'm assuming I have to use reflection of some sort but don't really understand it well enough to get started.

Any help is greatly appreciated.

I'm pretty new to reflection in general but I'm finding it very interesting and pretty difficult for some things. If you have any recommendations on readings or any other tips on how to better learn about reflection that'd be sweet as well!

EDIT/UPDATE after some more thought:

Would it be better just to use dynamic and call Invoke that way? Seems like it would work fine, but then that raises the question, of why you would ever go through the more difficult or longer process of setting up reflection to invoke something, instead of a simply dynamic call.

In any case, I'd still like to know how this would work using reflection, would be interesting to see

Upvotes: 3

Views: 1283

Answers (2)

xanatos
xanatos

Reputation: 111930

The problem is wrong and "artificial". Yes, you can use reflection, yes, you can use dynamic... But the "right" thing to do would be to change the signature to:

public (bool, object) SomeMethod(string par)

delegate:

Func<string, (bool, object)>

or

public bool SomeMethod(string par, out object obj)

delegate (note that you can't use Func<,>/Action<,>):

public delegate bool MyDelegate(string par, out object obj)

With this signature you don't need reflection to call the method and you don't need reflection to parse the return. Your return value/out is boxed by the method inside the object. The performance is still better than using reflection.

Other semi-good candidate could be:

Tuple<bool, type> SomeMethod(string par)

(where type is your changing type)

delegate:

Func<string, object>

or

Func<string, dynamic>

By using a Tuple<bool, type> you gain something: Tuple<> is a reference type, and delegates are contravariant in the return type, so you can "unify" them to object/dynamic (dynamic is an object with some information to the C# compiler that the programmer will try to do "bad things" to the object)

Now you'll have to use reflection/dynamic to access the Tuple<>.Item1 and Tuple<>.Item2.

The difference between using reflection and using dynamic is that by using reflection you can "cache" by type part of the reflection, so speeding up later uses of type methods, with dynamic this doesn't happen.

Upvotes: 1

Toan Nguyen
Toan Nguyen

Reputation: 11601

If you know the type of your function like Func you can cast it directly as below

 private static void InvokeFunctionDynamically<T>(T data)
    {            

        //1. Define the delegate 
        Func<string, bool, T> genericFunction = (name, isEnabled) =>
        {
            if(isEnabled)
            {
                return data;
            }

            return default(T);
        };

        // 2. demonstrate that the delegate is retrieved at the run time as an object
        object runtimeObject = genericFunction;


        //3. Cast it directly to the delegate type
        var result =((Func<string, bool, T>) runtimeObject)("hello", true);

        Console.WriteLine($"Result {result}");
    }

The results are below:

enter image description here

Upvotes: 0

Related Questions