Reflejo de C#: cargue el ensamblaje e invoque un método si existe
reflection invokemember (4)
utilice la reflexión para verificar si tiene un método llamado "CustomType MyMethod (byte [] a, int b)" y llámelo o envíe una excepción de lo contrario
Su código actual no está cumpliendo ese requisito. Pero puedes hacerlo bastante fácilmente con algo como esto:
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);
¿Es esto lo suficientemente bueno, o hay formas mejores / más rápidas / más cortas?
En lo que a mí respecta, esta es la mejor manera y realmente no hay nada más rápido por decir.
¿Y los constructores, dado que estos métodos no son estáticos? ¿Pueden simplemente ignorarse?
Aún tendrá que crear una instancia de t
como se muestra en mi ejemplo. Esto usará el constructor predeterminado sin argumentos. Si necesita pasar argumentos, puede, simplemente vea la documentación de MSDN y modifíquela como tal.
Quiero cargar un ensamblaje (su nombre está almacenado en una cadena), usar la reflexión para verificar si tiene un método llamado "CustomType MyMethod (byte [] a, int b)" y llamarlo o lanzar una excepción de lo contrario. Creo que debería hacer algo como esto, pero agradecería que alguien pudiera ofrecer el mismo consejo sobre la mejor manera de hacerlo:
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);
¿Es esto lo suficientemente bueno, o hay formas mejores / más rápidas / más cortas? ¿Y los constructores, dado que estos métodos no son estáticos? ¿Pueden simplemente ignorarse?
Al invocar métodos vacíos (), ¿está bien simplemente escribir t.InvokeMember (...) o siempre debe hacer Object obj = t.InvokeMember (...)?
Gracias por adelantado.
EDITAR He proporcionado un ejemplo de trabajo como una respuesta separada a continuación.
Dado que esta parece ser una pregunta popular, aquí está el ejemplo completo del código fuente sobre cómo hacerlo.
Supongamos que tenemos un ensamblado de muestra, MyAssembly.dll , con una clase MyClass . Queremos cargarlo dinámicamente e invocar sus métodos. Código 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);
}
}
}
Primero, nos gustaría crear una instancia de la clase usando el constructor MyClass(int initialX, int initialY)
, luego llamamos al método public int MyMethod(int count, string text)
. Así es como lo hace desde otro proyecto (por ejemplo, una aplicación de consola):
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);
}
Llamando al método estático public static void StaticMethod(int count, float radius)
ve así:
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);
Puede usar el tipo dinámico, que se resolverá en tiempo de ejecución.
Type type = Type.GetType(className, true);
dynamic instance = Activator.CreateInstance(type);
var response = instance.YourMethod();
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);
}
}
}