C # reflection – загрузить сборку и вызвать метод, если он существует

Я хочу загрузить сборку (ее имя хранится в строке), использовать reflection, чтобы проверить, есть ли у него метод «CustomType MyMethod (byte [] a, int b)» и вызывать его иначе или исключать исключение. Думаю, я должен был сделать что-то подобное, но был бы признателен, если бы кто-то мог предложить тот же совет о том, как это лучше всего сделать:

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 (…)?

Заранее спасибо.


EDIT Я представил рабочий пример в качестве отдельного ответа ниже.

используйте рефлексию, чтобы проверить, имеет ли он метод под названием «CustomType MyMethod (byte [] a, int b)» и вызывает его или генерирует исключение иначе

Ваш текущий код не выполняет это требование. Но вы можете довольно легко с чем-то вроде этого:

 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 и изменить его как таковой.

Поскольку это, кажется, популярный вопрос, вот полный пример исходного кода о том, как это сделать.

Предположим, у нас есть образец сборки MyAssembly.dll с classом MyClass . Мы хотим динамически загрузить его и вызвать его методы. Код 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); } } } 

Во-первых, мы хотели бы создать экземпляр classа с помощью конструктора 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(); 
  • Как создать экземпляр из строки в C #?
  • Загрузка DLL-файлов во время выполнения в C #
  • Почему GetType возвращает System.Int32 вместо Nullable ?
  • Разница между загрузкой classа с использованием ClassLoader и Class.forName
  • Поиск всех пространств имен в сборке с использованием Reflection (DotNET)
  • Отражение: как получить общий метод?
  • Поддержка отражения в C
  • Как я могу оценивать выражение C # динамически?
  • Получить свойства classа с помощью Typcript
  • Неплохо ли использовать рефлексию в модульном тестировании?
  • Reflection - получить имя атрибута и значение свойства
  • Давайте будем гением компьютера.