我试图通过参数反射来调用方法,我得到:
对象与目标类型不匹配
如果我调用没有参数的方法,它可以正常工作。如果我调用方法Test("TestNoParameters")
,则基于以下代码,它可以正常工作。但是,如果我拨打Test("Run")
,我会收到例外情况。我的代码有问题吗?
我最初的目的是传递一系列对象,例如public void Run(object[] options)
但这不起作用,我尝试了一些更简单的方法,例如字符串没有成功。
// 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);
}
}
}
}
}
答案 0 :(得分:215)
将“methodInfo”更改为“classInstance”,就像使用null参数数组调用一样。
result = methodInfo.Invoke(classInstance, parametersArray);
答案 1 :(得分:27)
你有错误
result = methodInfo.Invoke(methodInfo, parametersArray);
应该是
result = methodInfo.Invoke(classInstance, parametersArray);
答案 2 :(得分:21)
这是一个根本性的错误:
result = methodInfo.Invoke(methodInfo, parametersArray);
您正在MethodInfo
的实例上调用该方法。您需要传入要调用的对象类型的实例。
result = methodInfo.Invoke(classInstance, parametersArray);
答案 3 :(得分:10)
提供的解决方案不适用于从远程程序集加载的类型的实例。为此,这里有一个适用于所有情况的解决方案,它涉及通过CreateInstance调用返回的类型的显式类型重新映射。
这就是我需要创建classInstance的方法,因为它位于远程程序集中。
// sample of my CreateInstance call with an explicit assembly reference
object classInstance = Activator.CreateInstance(assemblyName, type.FullName);
但是,即使上面提供的答案,您仍然会得到相同的错误。以下是如何进行的:
// 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();
然后按照此处提到的其他用户进行操作。
答案 4 :(得分:4)
我会像这样使用它,它的方式更短,它不会给任何问题
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);
}
答案 5 :(得分:2)
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);
}
}
}
}
答案 6 :(得分:2)
我尝试使用上面提出的所有建议的答案,但似乎没有任何对我有用。所以我想在这里解释一下对我有用的东西。
我相信如果您正在调用某个方法,例如下面的Main
,或者甚至使用您问题中的单个参数,则只需将参数类型从string
更改为{{1}为了这个工作。我有一个类似下面的课程
object
然后你必须在调用它时将parameterArray传递给一个像下面的对象数组。您需要使用以下方法
//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]);
}
}
}
}
此方法可以轻松调用该方法,可以按以下方式调用
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 } );
}
}
}
答案 7 :(得分:1)
我正在通过反射调用加权平均值。并且使用了带有多个参数的方法。
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
答案 8 :(得分:0)
我之所以发布此答案,是因为许多访客从Google此处输入此问题。
"Values":{
.
.
"EventHub:Name": "your event hub name",
"EventHub:ConsumerGroup": "your event hub consumer group",
"EventHub:ConnectionString": "your event hub connection string"
}
当使用外部.dll而不是string result = this.GetType().GetMethod("Print").Invoke(this, new object[]{"firstParam", 157, "third_Parammmm" } );
时,您可以使用this.GetType()
。
答案 9 :(得分:0)
在.Net 4.7.2上调用从外部程序集加载的类中的方法,您可以在VB.net中使用以下代码
isBefore()