C# reflection - load assembly and invoke a method if it exists

后端 未结 4 522
不思量自难忘°
不思量自难忘° 2020-11-29 00:56

I want to load an assembly (its name is stored in a string), use reflection to check if it has a method called \"CustomType MyMethod(byte[] a, int b)\" and call it or throw

相关标签:
4条回答
  • 2020-11-29 01:11
    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);
                    }
                }
            }
    
    0 讨论(0)
  • 2020-11-29 01:16

    use reflection to check if it has a method called "CustomType MyMethod(byte[] a, int b)" and call it or throw an exception otherwise

    Your current code isn't fulfilling that requirement. But you can pretty easily with something like this:

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

    Is this good enough, or are there better/faster/shorter ways?

    As far as I'm concerned this is the best way and there isn't really anything faster per say.

    What about constructors, given that these methods are not static - can they simply be ignored?

    You are still going to have to create an instance of t as shown in my example. This will use the default constructor with no arguments. If you need to pass arguments you can, just see the MSDN documentation and modify it as such.

    0 讨论(0)
  • 2020-11-29 01:22

    You can use dynamic type whose will be resolved in runtime.

    Type type = Type.GetType(className, true);
    dynamic instance = Activator.CreateInstance(type);
    var response = instance.YourMethod();
    
    0 讨论(0)
  • 2020-11-29 01:24

    Since this seems to be a popular question, here's the complete source code example on how to do it.

    Suppose we have a sample assembly, MyAssembly.dll, with a class MyClass. We wish to dynamically load it and invoke its methods. MyAssembly code:

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

    First, we would like to create an instance of the class using the constructor MyClass(int initialX, int initialY), then call the method public int MyMethod(int count, string text). Here's how you do it from another project (e.g. a console application):

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

    Calling the static method public static void StaticMethod(int count, float radius) looks like this:

    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);
    
    0 讨论(0)
提交回复
热议问题