Invoke method by MethodInfo

2019-01-25 13:09发布

问题:

I want to invoke methods with a certain attribute. So I'm cycling through all the assemblies and all methods to find the methods with my attribute. Works fine, but how do I invoke a certain method when I only got it's MethodInfo.

AppDomain app = AppDomain.CurrentDomain;
Assembly[] ass = app.GetAssemblies();
Type[] types;
foreach (Assembly a in ass)
{
    types = a.GetTypes();
    foreach (Type t in types)
    {
        MethodInfo[] methods = t.GetMethods();
        foreach (MethodInfo method in methods)
        {
            // Invoke a certain method
        }
    }
}

The problem is that I don't know the instance of the class that contains that certain method. So I can't invoke it properly because the methods are not static. I also want to avoid creating a new instance of this class if possible.

回答1:

This strikes me as an issue in terms of the problem definition rather than coding.

Instance methods depend on which instance they're called on - it makes no sense to call an instance method without caring about what it's called on. (As Martin says, an instance method which doesn't care which instance it's being called on should almost always be static. The only immediate exception I can think of for this is virtual methods, where the instance implicitly specifies which implementation to use.)

Work out what it really means in your context for there to be an annotated instance method. Why are you trying to invoke methods anyway? What's the bigger picture? What context do you have? I strongly suspect you'll want some notion of a context - a collection of objects which you can call the instance methods on.



回答2:

Non-static methods are instance specific so you must instantiate the class to invoke the method. If you have the ability to change the code where it is defined and the method doesn't require itself to be part of an instance (it doesn't access or modify any non-static properties or methods inside the class) then best practice would be to make the method static anyway.

Assuming you can't make it static then the code you need is as follows:

    foreach (Type t in types)
    {
            object instance = Activator.CreateInstance(t);

            MethodInfo[] methods = t.GetMethods();
            foreach (MethodInfo method in methods)
            {                    
                method.Invoke(instance, params...);    
            }
    }


回答3:

Actually, I think what you need to do is to create a list of the existing objects and then search the list. So as you create these invokable objects, you would store them into the list (or perhaps the list should be a list of objects of some other kind that also has a description of the invokable object). Then you can scan the list at runtime, find the one that matches the type of event you are handling, and then look up its methodInfo and call .Invoke on the method info, assuming thats what you want to do. You would also need to pass in the appropriate arguments, but you can do that by creating a vector of objects of the right types.