Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically invoke a method given a Type variable

Tags:

c#

.net

unity3d

My Goal: I have a system where I would like others to be able to add a C# script that contains a specific method that I can lookup and execute from within another class at runtime.

My Approach: I created an interface with a method so I can loop through any class that implements the interface using reflection and list them then have the method name be the same between all those classes.

I have class that has an enum of all the classes found during the lookup and the user can select between them at runtime.

I now need to be able to get the method of the selected class type and invoke it's method, the problem is I know the name of the method for certain but the type of the class is stored as a variable.

The Code:

//Pseudo code from memory:

            //Possible solution 1:
            Type selectedType = typeSelectedByEnum;
            MethodInfo genericMethod = selectedType.GetMethod("TheInterfaceMethod").MakeGenericMethod(selectedType);
            genericMethod.Invoke(selectedType, new object[0]);

            //Possible solution 2: (however I would much prefer to use something avaliable prior to .NET 4.6)
            Type selectedType = typeSelectedByEnum;
            dynamic changedObj = Convert.ChangeType(selectedType, selectedType);//-Something here needs to implement IConvertable, how would I set this up?
            changedObj.TheInterfaceMethod();

            //Possible solution 3:

            //Your solution??!

Any help appreciated, at this point I have tried many things and am open to just about any possible runtime alternative. I can provide more code if necessary.

like image 228
FirefightGI Avatar asked Dec 06 '17 22:12

FirefightGI


1 Answers

Since you are using an interface to mark classes that have your method "TheInterfaceMethod", then the method must not be static. That means that you need an instance of the object in which to invoke the method on. The Activator class provides an easy way to create instances of objects, but it does require a default constructor with visibility (most likely a public constructor in your case).

I also noticed on potential issue with your example which is that you were calling "MakeGenericMethod". This is only necessary if the function has some generic type parameter that you need to define to have a meaningful function. Such as this interface:

    interface IInterfaceWithGenericMethod
    {
        void TheInterfaceMethod<T>();
    }

Here's an example using your variables:

        Type selectedType = typeSelectedByEnum;
        MethodInfo method = selectedType.GetMethod("TheInterfaceMethod");
        object obj = Activator.CreateInstance(selectedType);
        method.Invoke(obj, null);

Interestingly, once you have an instance of the object, you don't need reflection to invoke the method anymore. You can simply cast it to your interface. Let's assume your interface is called IAwesomeInterface:

        Type selectedType = typeSelectedByEnum;
        object obj = Activator.CreateInstance(selectedType);
        IAwesomeInterface converted = obj as IAwesomeInterface;
        converted.TheInterfaceMethod();
like image 133
kriskalish Avatar answered Nov 03 '22 21:11

kriskalish