C#'找不到'现有方法

时间:2011-01-16 21:20:54

标签: c# .net reflection assemblies runtime

问候!  我一直在用C#和它的程序集搞砸(有点)。所以我发现了一个有趣的功能,如动态加载程序集和调用其类成员。一点谷歌和我在这里,写一些'装配探险家'。 (我使用了来自hereherehere的部分代码,而且没有任何代码可以给出任何预期结果。

但是我发现了一个小错误:当我尝试从程序集调用类方法时,我已经加载了,应用程序引发了MissingMethod异常。我确定我正在加载的DLL包含我试图调用的类和方法(我的应用程序确保我以及 RedGate的.NET Reflector ):

alt text

主要的应用程序代码似乎还可以,我开始思考我的DLL是不是错了......啊,我把这两个项目放到一个解决方案中,但我不认为这可能会导致任何麻烦。是的,DLL项目具有“类库”目标,而主应用程序具有“控制台应用程序”目标。

所以,问题是:他们有什么问题?

以下是一些源代码:

DLL来源:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassLibrary1
{
    public class Class1
    {
        public void Main()
        {
            System.Console.WriteLine("Hello, World!");
        }
    }
}

主要应用来源:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly asm = Assembly.LoadFrom(@"a\long\long\path\ClassLibrary1.dll");

            try
            {
                foreach (Type t in asm.GetTypes())
                {
                    if (t.IsClass == true && t.FullName.EndsWith(".Class1"))
                    {
                        object obj = Activator.CreateInstance(t);
                        object res = t.InvokeMember("Main", BindingFlags.Default | BindingFlags.InvokeMethod, null, obj, null); // Exception is risen from here
                    }
                }
            }
            catch (Exception e)
            {
                System.Console.WriteLine("Error: {0}", e.Message);
            }

            System.Console.ReadKey();
        }
    }
}

UPD:适用于一个案例 - 当DLL方法不带参数时:

DLL类(如果方法不是静态的,也可以使用):

public class Class1
{
    public static void Main()
    {
        System.Console.WriteLine("Hello, World!");
    }
}

方法调用代码:

object res = t.InvokeMember("Main", BindingFlags.Default | BindingFlags.InvokeMethod, null, null, null);

3 个答案:

答案 0 :(得分:4)

为什么要使用实例(Activator.CreateInstance(t))来调用静态方法?它应该是:

t.InvokeMember(
     "Main", 
     BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, 
     null, 
     null, 
     new object[] { new string[0] }
);

此定义的方法也不返回任何值,因此无需为其指定返回变量。

为了清除所有误解,我在这里创建了一个完整的工作演示:http://www.mediafire.com/?n7h9b8ghomfv17d

答案 1 :(得分:3)

您可能会错误地调用InvokeMember()参数。这是一个有效的样本:

using System;
using System.Reflection;

class Program {
    static void Main(string[] args) {
        if (args.Length > 0) Console.WriteLine(args[0]);
        else {
            Assembly asm = Assembly.LoadFrom(Assembly.GetEntryAssembly().Location);
            foreach (Type t in asm.GetTypes()) {
                if (t.IsClass == true && t.FullName.EndsWith(".Program")) {
                    //object obj = Activator.CreateInstance(t);
                    object res = t.InvokeMember("Main",
                        BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod,
                        null, null,
                        new object[] { new string[] { "Invoked" } });
                }
            }
        }
    }
}
  • 请注意Main()方法不是公共的,因此BindingFlags.NonPublic
  • 注意Main()方法是如何静态的,因此BindingFlags.Static
  • 出于同样的原因,为目标参数
  • 传递null
  • 出于同样的原因,不需要CreateInstance
  • 请注意Main()方法如何获取string []参数,您必须传递它以获取Reflection以找到正确的方法重载。

遵循Main()方法的相同逻辑:

                object res = t.InvokeMember("Main",
                    BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,
                    null, obj,
                    new object[] { });

答案 2 :(得分:2)

InvokeMember的最后一个参数是包含方法参数的Objects数组。

你在那里传递null,你应该传递一个包含单个元素(一个字符串数组)的对象数组。