简体   繁体   中英

What better ways are there to instantiate a class specified at runtime, and call a method on that instance?

I have a command line application that has to be able to perform one of a number of discrete tasks, given a verb as a command line argument. Each task is handled by a class, each of which implements an interface containing a method Execute() . I'm trying to do this without using if or switch statements. So far, what I have is this:

var taskTypeName = $"MyApp.Tasks.{invokedVerb}Task";
var taskType = Type.GetType(taskTypeName, false);
var task = Activator.CreateInstance(taskType) as IMaintenanceTask;
task.Execute();

task is of type IMaintenanceTask , which is fundamentally what I'm trying to achieve. I'd prefer to avoid using dynamic - my understanding is that if it's only used once, like here, I won't see any of the benefits of caching, making it just reflection in fewer keystrokes.

Is this approach (or something along the same lines) likely to noticeably affect performance? I know it definitely increases the chance of runtime exceptions/bugs, but that's partly mitigated by the fact that this application is only going to be run via scripts; it will only deal with predictable input - also this will be the only place in the code that behaves dynamically. Is what I'm trying to achieve sensible? Or would it be better to just do this the boring normal way, via just switching on the input and constructing each type of task via a normal, compile-time constructor, and calling .Execute() on that.

Don't worry about the performance of a dispatch mechanism, unless it is in a tight loop. Switching a single direct method call to a single call through dynamic , a single call through reflection, a single call through emit API, or a single call through compiled LINQ expression will not make a detectable difference in execution time of your application. The time it takes operating system to start up your application is several orders of magnitude higher than the time it takes your application to decide what method to call, so your solution is as good as a switch , except it is a lot shorter (which is a good thing).

As it is just one time call, you can go with your solution. Just add a few conditions to avoid exception chances.

var taskTypeName = $"MyApp.Tasks.{invokedVerb}Task";
var taskType = Type.GetType(taskTypeName, false);
if (taskType != null && typeof(IMaintenanceTask).IsAssignableFrom(taskType))
{
    var task = Activator.CreateInstance(taskType) as IMaintenanceTask;
    task.Execute();
}

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