Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reflection: How to Invoke Method with parameters

People also ask

How is a method invoked with parameter?

The invoke () method of Method class Invokes the underlying method represented by this Method object, on the specified object with the specified parameters. Individual parameters automatically to match primitive formal parameters.

How can you invoke an object method in C#?

To invoke a method and omit optional parameters, call Type. InvokeMember instead. If this method overload is used to invoke an instance constructor, the object supplied for obj is reinitialized; that is, all instance initializers are executed. The return value is null .

What does it mean to invoke a method?

To "invoke" appears to mean to call a method indirectly through an intermediary mechanism.


Change "methodInfo" to "classInstance", just like in the call with the null parameter array.

  result = methodInfo.Invoke(classInstance, parametersArray);

You have a bug right there

result = methodInfo.Invoke(methodInfo, parametersArray);

it should be

result = methodInfo.Invoke(classInstance, parametersArray);

A fundamental mistake is here:

result = methodInfo.Invoke(methodInfo, parametersArray); 

You are invoking the method on an instance of MethodInfo. You need to pass in an instance of the type of object that you want to invoke on.

result = methodInfo.Invoke(classInstance, parametersArray);

The provided solution does not work for instances of types loaded from a remote assembly. To do that, here is a solution that works in all situations, which involves an explicit type re-mapping of the type returned through the CreateInstance call.

This is how I need to create my classInstance, as it was located in a remote assembly.

// sample of my CreateInstance call with an explicit assembly reference
object classInstance = Activator.CreateInstance(assemblyName, type.FullName); 

However, even with the answer provided above, you'd still get the same error. Here is how to go about:

// first, create a handle instead of the actual object
ObjectHandle classInstanceHandle = Activator.CreateInstance(assemblyName, type.FullName);
// unwrap the real slim-shady
object classInstance = classInstanceHandle.Unwrap(); 
// re-map the type to that of the object we retrieved
type = classInstace.GetType(); 

Then do as the other users mentioned here.


I would use it like this, its way shorter and it won't give any problems

        dynamic result = null;
        if (methodInfo != null)
        {
            ParameterInfo[] parameters = methodInfo.GetParameters();
            object classInstance = Activator.CreateInstance(type, null);
            result = methodInfo.Invoke(classInstance, parameters.Length == 0 ? null : parametersArray);
        }

I tried to work with all the suggested answers above but nothing seems to work for me. So i am trying to explain what worked for me here.

I believe if you are calling some method like the Main below or even with a single parameter as in your question, you just have to change the type of parameter from string to object for this to work. I have a class like below

//Assembly.dll
namespace TestAssembly{
    public class Main{

        public void Hello()
        { 
            var name = Console.ReadLine();
            Console.WriteLine("Hello() called");
            Console.WriteLine("Hello" + name + " at " + DateTime.Now);
        }

        public void Run(string parameters)
        { 
            Console.WriteLine("Run() called");
            Console.Write("You typed:"  + parameters);
        }

        public string TestNoParameters()
        {
            Console.WriteLine("TestNoParameters() called");
            return ("TestNoParameters() called");
        }

        public void Execute(object[] parameters)
        { 
            Console.WriteLine("Execute() called");
           Console.WriteLine("Number of parameters received: "  + parameters.Length);

           for(int i=0;i<parameters.Length;i++){
               Console.WriteLine(parameters[i]);
           }
        }

    }
}

Then you have to pass the parameterArray inside an object array like below while invoking it. The following method is what you need to work

private void ExecuteWithReflection(string methodName,object parameterObject = null)
{
    Assembly assembly = Assembly.LoadFile("Assembly.dll");
    Type typeInstance = assembly.GetType("TestAssembly.Main");

    if (typeInstance != null)
    {
        MethodInfo methodInfo = typeInstance.GetMethod(methodName);
        ParameterInfo[] parameterInfo = methodInfo.GetParameters();
        object classInstance = Activator.CreateInstance(typeInstance, null);

        if (parameterInfo.Length == 0)
        {
            // there is no parameter we can call with 'null'
            var result = methodInfo.Invoke(classInstance, null);
        }
        else
        {
            var result = methodInfo.Invoke(classInstance,new object[] { parameterObject } );
        }
    }
}

This method makes it easy to invoke the method, it can be called as following

ExecuteWithReflection("Hello");
ExecuteWithReflection("Run","Vinod");
ExecuteWithReflection("TestNoParameters");
ExecuteWithReflection("Execute",new object[]{"Vinod","Srivastav"});