简体   繁体   中英

Create an instance of the DeclaringType of a method: Activator.CreateInstance

I once again am struggling with reflection. I just give you the piece of code that my debugger does not bite:

public bool HandleCommand(string command)
        {
            
            MethodInfo m = methods.FirstOrDefault(t => t.GetCustomAttribute<CommandAttribute>().Name == command);
            ICommandSet set =(m.DeclaringType)Activator.CreateInstance(m.DeclaringType);
            m?.Invoke(set, null);
            return true;
        }

Basically, this code is inside a class called CommandHandler. When it's constructed, it loops over all the types in the executing assembly that implement a certain interface, and store all their methods that have a CustomAttribute attached to it in List; For this question's purpose I just assume that everything is working there. The attribute has just one property:

[AttributeUsage(AttributeTargets.Method)]
    public class CommandAttribute : Attribute
    {
        public string Name { get; set; }

        public CommandAttribute(string name)
        {
            Name = name;
        }
    }

Now in the method you saw above, the HandleCommand() method, I store the method which's name property is equal to the string I passed in in a MethodInfo m. Now my question essentially is, how I properly Invoke this method. m.Invoke needs an object that calls it, and because passing in "this" does not work, and examples online always passed in an instance of the class it was defined in, I figured I needed to create an instance of the class m was defined in and just pass this into the Invoke() method. In practice, this is a lot harder than I thought, and my best guess is what you can see above, with the activator.

ICommandSet set =(m.DeclaringType)Activator.CreateInstance(m.DeclaringType);

First of all, I know for sure that the class that m is declared in implements ICommandSet, because this is a creterium for a type to be inspected for the methods. So this is why I say "ICommandSet set". Then the Activator shall create this instance. But it does not work. The only error message provided states that m is a variable but is used like a type. However, when I pass it in as a param to Activator.CreateInstance() the compiler seems to dig it just fine. I absolutely don't know how I might fix this problem, as I don't really understand what is the problem. Is there anyone out there who can help me?

Also, all the methods are defined in different classes and even projects, so I don't know which class the methods are defined in.

The reason you're receiving this is your syntax is wrong. You cannot perform a cast with a variable dereference as the desire type. As you already know you wish to treat "set" as an "ICommandSet" cast to that instead.

var set = (ICommandSet) Activator.CreateInstance(m.DeclaringType);

You can also do it safe

var set = Activator.CreateInstance(m.DeclaringType) as ICommandSet;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM