221

パラメータを使用してリフレクションを介してメソッドを呼び出そうとしていますが、次のようになります。

オブジェクトがターゲット タイプと一致しません

パラメータなしでメソッドを呼び出すと、正常に動作します。メソッドを呼び出すと、次のコードに基づいて、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);
                }
            }
        }
    }
}
4

10 に答える 10

254

null パラメータ配列を使用した呼び出しと同様に、「methodInfo」を「classInstance」に変更します。

  result = methodInfo.Invoke(classInstance, parametersArray);
于 2010-02-04T19:08:19.890 に答える
30

そこにバグがあります

result = methodInfo.Invoke(methodInfo, parametersArray);

そのはず

result = methodInfo.Invoke(classInstance, parametersArray);
于 2010-02-04T19:11:35.923 に答える
12

提供されたソリューションは、リモート アセンブリから読み込まれた型のインスタンスに対しては機能しません。これを行うには、すべての状況で機能するソリューションを次に示します。これには、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(); 

次に、ここで言及されている他のユーザーと同じようにします。

于 2011-07-21T09:32:03.600 に答える
5

上記のすべての提案された回答で作業しようとしましたが、何もうまくいかないようです。だから私はここで私のために何がうまくいったかを説明しようとしています.

以下のようなメソッドを呼び出している場合、Mainまたは質問のように単一のパラメーターを使用している場合でも、パラメーターのタイプを から に変更するだけで機能すると思いstringますobject。私は以下のようなクラスを持っています

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

    }
}

次に、呼び出し中に以下のようにオブジェクト配列内に parameterArray を渡す必要があります。次の方法は、作業に必要なものです

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

このメソッドを使用すると、メソッドを簡単に呼び出すことができます。次のように呼び出すことができます。

ExecuteWithReflection("Hello");
ExecuteWithReflection("Run","Vinod");
ExecuteWithReflection("TestNoParameters");
ExecuteWithReflection("Execute",new object[]{"Vinod","Srivastav"});
于 2018-03-07T19:55:01.413 に答える