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