Keywords: C# | Reflection | Method_Invocation | Parameter_Passing | MethodInfo.Invoke
Abstract: This article provides an in-depth exploration of parameter passing in C# reflection method invocation, focusing on the common "object does not match target type" error. Through comparative analysis of incorrect and correct implementations, it explains the proper usage of MethodInfo.Invoke method, including instance object passing and parameter array construction. With detailed code examples, the article offers comprehensive solutions and best practices to help developers master core techniques of reflection method invocation.
Fundamental Concepts of Reflection Method Invocation
In C# programming, reflection mechanism provides the capability to dynamically invoke methods and access type information at runtime. The MethodInfo.Invoke method serves as the core tool for dynamic method invocation, with its basic syntax:
object result = methodInfo.Invoke(obj, parameters);
Where the obj parameter represents the instance object to which the method belongs, and for instance methods, a valid object instance must be provided; the parameters parameter is an object array containing the actual parameter values to be passed to the method.
Common Error Analysis and Solutions
During reflection method invocation, developers frequently encounter the "object does not match target type" error. This error typically stems from misunderstandings about the parameters of the MethodInfo.Invoke method.
Incorrect Code Example
The following code demonstrates a typical incorrect implementation:
// Incorrect implementation
object[] parametersArray = new object[] { "Hello" };
result = methodInfo.Invoke(methodInfo, parametersArray);
The problem with this implementation is that it passes the methodInfo object itself as the first parameter to the Invoke method, rather than the instance object to which the method belongs.
Correct Implementation Approach
The correct implementation should use the previously created class instance:
// Correct implementation
object classInstance = Activator.CreateInstance(type, null);
object[] parametersArray = new object[] { "Hello" };
result = methodInfo.Invoke(classInstance, parametersArray);
The key difference here is that the first parameter passed is classInstance, which is the actual instance object of the class to which the method belongs.
Detailed Specifications for Parameter Passing
Parameter passing in MethodInfo.Invoke method must strictly adhere to the following rules:
Parameter Array Construction
The parameter array must exactly match the method signature:
// For method: public void Run(string parameters)
object[] parametersArray = new object[] { "Hello" };
// For method: public void Run(object[] options)
object[] parametersArray = new object[] { new object[] { "option1", "option2" } };
Static Method Handling
For static methods, the first parameter should be set to null:
// Static method invocation
result = methodInfo.Invoke(null, parametersArray);
Complete Example Code
Below is a complete example of reflection method invocation implementation:
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)
{
// Parameterless method invocation
result = methodInfo.Invoke(classInstance, null);
}
else
{
// Parameterized method invocation
object[] parametersArray = new object[] { "Hello" };
result = methodInfo.Invoke(classInstance, parametersArray);
}
}
}
}
}
Exception Handling and Debugging Techniques
Proper exception handling is crucial during reflection method invocation:
Parameter Type Validation
Validate parameter type matching before invocation:
ParameterInfo[] methodParameters = methodInfo.GetParameters();
if (methodParameters.Length != parametersArray.Length)
{
throw new ArgumentException("Parameter count mismatch");
}
for (int i = 0; i < methodParameters.Length; i++)
{
if (parametersArray[i] != null &&
!methodParameters[i].ParameterType.IsInstanceOfType(parametersArray[i]))
{
throw new ArgumentException($"Parameter {i} type mismatch");
}
}
Error Message Analysis
When encountering "object does not match target type" error, check:
- Whether the first parameter is a valid instance of the method's class
- Whether the parameter array exactly matches the method signature
- Whether parameter types can be implicitly converted to target types
Performance Optimization Recommendations
Reflection invocation has performance overhead compared to direct invocation. Consider the following optimization strategies:
Cache MethodInfo Objects
private static readonly Dictionary<string, MethodInfo> methodCache =
new Dictionary<string, MethodInfo>();
public MethodInfo GetCachedMethod(Type type, string methodName)
{
string key = $"{type.FullName}.{methodName}";
if (!methodCache.ContainsKey(key))
{
methodCache[key] = type.GetMethod(methodName);
}
return methodCache[key];
}
Use Delegate.CreateDelegate
For frequently invoked methods, create delegates to improve performance:
public delegate void StringMethodDelegate(string parameter);
public StringMethodDelegate CreateDelegate(MethodInfo method, object target)
{
return (StringMethodDelegate)Delegate.CreateDelegate(
typeof(StringMethodDelegate), target, method);
}
Conclusion
Reflection method invocation is a powerful tool in C# programming, but requires proper understanding of the parameter passing mechanism in MethodInfo.Invoke method. Key points include: ensuring the first parameter passes the correct instance object, exact matching of parameter arrays with method signatures, and proper handling of static method invocation. Through the analysis and examples in this article, developers can avoid common parameter passing errors and write robust and reliable reflection code.