C#reflection – 加载程序集并调用方法(如果存在)

我想加载一个程序集(它的名称存储在一个字符串中),使用reflection来检查它是否有一个名为“CustomType MyMethod(byte [] a,int b)”的方法并调用它或者抛出exception。 我想我应该做这样的事情,但如果有人可以就如何做到这一点提出相同的建议,我将不胜感激:

Assembly asm = Assembly.Load("myAssembly"); /* 1. does it matter if write myAssembly or myAssembly.dll? */ Type t = asm.GetType("myAssembly.ClassName"); // specify parameters byte[] a = GetParamA(); int b = GetParamB(); object[] params = new object[2]; params[0] = a; params[1] = b; /* 2. invoke method MyMethod() which returns object "CustomType" - how do I check if it exists? */ /* 3. what's the meaning of 4th parameter (t in this case); MSDN says this is "the Object on which to invoke the specified member", but isn't this already accounted for by using t.InvokeMember()? */ CustomType result = t.InvokeMember("MyMethod", BindingFlags.InvokeMethod, null, t, params); 

这是否足够好,还是有更好/更快/更短的方式? 那么构造函数呢,假设这些方法不是静态的 – 它们可以简单地被忽略吗?

在调用void Methods()时,只需编写t.InvokeMember(…)或者你应该总是执行Object obj = t.InvokeMember(…)吗?

提前致谢。


编辑我提供了一个工作示例,作为下面单独的答案。

使用reflection来检查它是否有一个名为“CustomType MyMethod(byte [] a,int b)”的方法并调用它或抛出exception否则

您当前的代码未满足该要求。 但你可以很容易地用这样的东西:

 var methodInfo = t.GetMethod("MyMethod", new Type[] { typeof(byte[]), typeof(int) }); if (methodInfo == null) // the method doesn't exist { // throw some exception } var o = Activator.CreateInstance(t); var result = methodInfo.Invoke(o, params); 

这是否足够好,还是有更好/更快/更短的方式?

就我而言,这是最好的方式,而且每次发言都没有什么比这更快的了。

那么构造函数呢,假设这些方法不是静态的 – 它们可以简单地被忽略吗?

您仍然需要创建一个t实例,如我的示例所示。 这将使用没有参数的默认构造函数。 如果您需要传递参数,只需查看MSDN文档并进行相应修改即可。

由于这似乎是一个流行的问题,这里是完整的源代码示例,如何做到这一点。

假设我们有一个MyAslass类的示例程序集MyAssembly.dll 。 我们希望动态加载它并调用它的方法。 MyAssembly代码:

 namespace MyAssembly { public class MyClass { public int X { get; set; } public int Y { get; set; } public MyClass(int initialX, int initialY) { X = initialX; Y = initialY; } public int MyMethod(int count, string text) { Console.WriteLine("This is a normal method."); Console.WriteLine("Count: {0}", count); Console.WriteLine("Text: {0}", text); return this.X + this.Y; } public static void StaticMethod(int count, float radius) { Console.WriteLine("This is a static method call."); Console.WriteLine("Count: {0}", count); Console.WriteLine("Radius: {0}", radius); } } } 

首先,我们想使用构造函数MyClass(int initialX, int initialY)创建类的实例,然后调用方法public int MyMethod(int count, string text) 。 以下是您从另一个项目(例如控制台应用程序)执行此操作的方法:

 static void Main(string[] args) { // // 1. Load assembly "MyAssembly.dll" from file path. Specify that we will be using class MyAssembly.MyClass // Assembly asm = Assembly.LoadFrom(@"C:\Path\MyAssembly.dll"); Type t = asm.GetType("MyAssembly.MyClass"); // // 2. We will be invoking a method: 'public int MyMethod(int count, string text)' // var methodInfo = t.GetMethod("MyMethod", new Type[] { typeof(int), typeof(string) }); if (methodInfo == null) { // never throw generic Exception - replace this with some other exception type throw new Exception("No such method exists."); } // // 3. Define parameters for class constructor 'MyClass(int initialX, int initialY)' // object[] constructorParameters = new object[2]; constructorParameters[0] = 999; // First parameter. constructorParameters[1] = 2; // Second parameter. // // 4. Create instance of MyClass. // var o = Activator.CreateInstance(t, constructorParameters); // // 5. Specify parameters for the method we will be invoking: 'int MyMethod(int count, string text)' // object[] parameters = new object[2]; parameters[0] = 124; // 'count' parameter parameters[1] = "Some text."; // 'text' parameter // // 6. Invoke method 'int MyMethod(int count, string text)' // var r = methodInfo.Invoke(o, parameters); Console.WriteLine(r); } 

调用静态方法public static void StaticMethod(int count, float radius)如下所示:

 var methodInfoStatic = t.GetMethod("StaticMethod"); if (methodInfoStatic == null) { // never throw generic Exception - replace this with some other exception type throw new Exception("No such static method exists."); } // Specify parameters for static method: 'public static void MyMethod(int count, float radius)' object[] staticParameters = new object[2]; staticParameters[0] = 10; staticParameters[1] = 3.14159f; // Invoke static method methodInfoStatic.Invoke(o, staticParameters); 
 Assembly assembly = Assembly.LoadFile("myAssembly"); Type type = assembly.GetType("myAssembly.ClassName"); if (type != null) { MethodInfo methodInfo = type.GetMethod("MyMethod"); 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); } } } 

您可以使用将在运行时解析的动态类型。

 Type type = Type.GetType(className, true); dynamic instance = Activator.CreateInstance(type); var response = instance.YourMethod();