问候! 我一直在用C#和它的程序集搞砸(有点)。所以我发现了一个有趣的功能,如动态加载程序集和调用其类成员。一点谷歌和我在这里,写一些'装配探险家'。 (我使用了来自here,here和here的部分代码,而且没有任何代码可以给出任何预期结果。
但是我发现了一个小错误:当我尝试从程序集调用类方法时,我已经加载了,应用程序引发了MissingMethod异常。我确定我正在加载的DLL包含我试图调用的类和方法(我的应用程序确保我以及 RedGate的.NET Reflector ):
主要的应用程序代码似乎还可以,我开始思考我的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);
答案 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()方法的相同逻辑:
object res = t.InvokeMember("Main",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,
null, obj,
new object[] { });
答案 2 :(得分:2)
InvokeMember
的最后一个参数是包含方法参数的Objects数组。
你在那里传递null
,你应该传递一个包含单个元素(一个字符串数组)的对象数组。