250

I am trying to invoke a method via reflection with parameters and I get:

object does not match target type

If I invoke a method without parameters, it works fine. Based on the following code if I call the method Test("TestNoParameters"), it works fine. However if I call Test("Run"), I get an exception. Is something wrong with my code?

My initial purpose was to pass an array of objects e.g. public void Run(object[] options) but this did not work and I tried something simpler e.g. string without success.

// Assembly1.dll namespace TestAssembly { public class Main { public void Run(string parameters) { // Do something... } public void TestNoParameters() { // Do something... } } } // Executing Assembly.exe public class TestReflection { public void Test(string methodName) { Assembly assembly = Assembly.LoadFile("...Assembly1.dll"); Type type = assembly.GetType("TestAssembly.Main"); if (type != null) { MethodInfo methodInfo = type.GetMethod(methodName); if (methodInfo != null) { object result = null; ParameterInfo[] parameters = methodInfo.GetParameters(); object classInstance = Activator.CreateInstance(type, null); if (parameters.Length == 0) { // This works fine result = methodInfo.Invoke(classInstance, null); } else { object[] parametersArray = new object[] { "Hello" }; // The invoke does NOT work; // it throws "Object does not match target type" result = methodInfo.Invoke(methodInfo, parametersArray); } } } } } 
3
  • 7
    the correct line would be object[] parametersArray = new object[] { new object[] { "Hello" } }; Commented Mar 15, 2018 at 13:35
  • If you know that there is a type that is always loaded first, you can put a static ctor on it. Commented Feb 10, 2021 at 10:57
  • I suggest you look at Nick's comment above to avoid parameter errors. Commented Feb 7, 2022 at 17:54

10 Answers 10

274

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

 result = methodInfo.Invoke(classInstance, parametersArray); 
Sign up to request clarification or add additional context in comments.

3 Comments

This works, except when working with an instance of a remote assembly. The problem was that it spills out the same error which isn't very helpful. I spent several hours trying to fix it, and posted a new general solution to both my case and the one provided here. In case anyone may need it :)
if the parameters are of multiple types, what should the array be like? an array of objects??
Yes, it should be an object[] if there are multiple types in arguments
34

You have a bug right there

result = methodInfo.Invoke(methodInfo, parametersArray); 

it should be

result = methodInfo.Invoke(classInstance, parametersArray); 

Comments

27

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); 

Comments

12

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.

Comments

9

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 in the class 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 created an example class like below

Example Assembly.dll

//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 static string StaticString() { return "static string example"; } 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 call with MethodName & parameterList to invoke the method from Assembly.dll above.

Invoker ExecuteMethod

private object ExecuteMethod(string methodName,object parameterObject = null) { Assembly assembly = Assembly.LoadFile("Assembly.dll"); Type typeInstance = assembly.GetType("TestAssembly.Main"); MethodInfo methodInfo = typeInstance.GetMethod(methodName); ParameterInfo[] parameterInfo = methodInfo.GetParameters(); object result = null; if (typeInstance != null) //non static { if(methodInfo.IsStatic == false) { //instance is needed to invoke the method object classInstance = Activator.CreateInstance(typeInstance, null); if (parameterInfo.Length == 0) { // there is no parameter we can call with 'null' result = methodInfo.Invoke(classInstance, null); } else { result = methodInfo.Invoke(classInstance,new object[] { parameterObject } ); } } else //handle static { if (parameterInfo.Length == 0) { // there is no parameter we can call with 'null' result = methodInfo.Invoke(null, null); } else { result = methodInfo.Invoke(null,new object[] { parameterObject } ); } } } return result; } 

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

Usage Example

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

4 Comments

This does not work with static methods.
@DonnyV. For static you can invoke with methodInfo.Invoke(null, null); . please see the updated code
I have 2 constructors one with parameters and other without. How can I invoke the constructor with parameters? Thank you very much!
@DavidCon the constructor is invoked with Activator.CreateInstance method here which calls the default constructor and if you see the documentation learn.microsoft.com/en-us/dotnet/api/… you can set different parameters to invoke different constructors.
8

I'am posting this answer because many visitors enter here from google for this problem.


string result = this.GetType().GetMethod("Print").Invoke(this, new object[]{"firstParam", 157, "third_Parammmm" } ); 

when external .dll -instead of this.GetType(), you might use typeof(YourClass).

Comments

6

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); } 

Comments

4
 Assembly assembly = Assembly.LoadFile(@"....bin\Debug\TestCases.dll"); //get all types var testTypes = from t in assembly.GetTypes() let attributes = t.GetCustomAttributes(typeof(NUnit.Framework.TestFixtureAttribute), true) where attributes != null && attributes.Length > 0 orderby t.Name select t; foreach (var type in testTypes) { //get test method in types. var testMethods = from m in type.GetMethods() let attributes = m.GetCustomAttributes(typeof(NUnit.Framework.TestAttribute), true) where attributes != null && attributes.Length > 0 orderby m.Name select m; foreach (var method in testMethods) { MethodInfo methodInfo = type.GetMethod(method.Name); if (methodInfo != null) { object result = null; ParameterInfo[] parameters = methodInfo.GetParameters(); object classInstance = Activator.CreateInstance(type, null); if (parameters.Length == 0) { // This works fine result = methodInfo.Invoke(classInstance, null); } else { object[] parametersArray = new object[] { "Hello" }; // The invoke does NOT work; // it throws "Object does not match target type" result = methodInfo.Invoke(classInstance, parametersArray); } } } } 

Comments

1

I m invoking the weighted average through reflection. And had used method with more than one parameter.

Class cls = Class.forName(propFile.getProperty(formulaTyp));// reading class name from file Object weightedobj = cls.newInstance(); // invoke empty constructor Class<?>[] paramTypes = { String.class, BigDecimal[].class, BigDecimal[].class }; // 3 parameter having first is method name and other two are values and their weight Method printDogMethod = weightedobj.getClass().getMethod("applyFormula", paramTypes); // created the object return BigDecimal.valueOf((Double) printDogMethod.invoke(weightedobj, formulaTyp, decimalnumber, weight)); calling the method 

Comments

0

On .Net 4.7.2 to invoke a method inside a class loaded from an external assembly you can use the following code in VB.net

 Dim assembly As Reflection.Assembly = Nothing Try assembly = Reflection.Assembly.LoadFile(basePath & AssemblyFileName) Dim typeIni = assembly.[GetType](AssemblyNameSpace & "." & "nameOfClass") Dim iniClass = Activator.CreateInstance(typeIni, True) Dim methodInfo = typeIni.GetMethod("nameOfMethod") 'replace nothing by a parameter array if you need to pass var. paramenters Dim parametersArray As Object() = New Object() {...} 'without parameters is like this Dim result = methodInfo.Invoke(iniClass, Nothing) Catch ex As Exception MsgBox("Error initializing main layout:" & ex.Message) Application.Exit() Exit Sub End Try 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.