2016-09-14 1 views
1

Ich habe eine Befehlszeilenanwendung, die in der Lage sein muss, eine von einer Anzahl von diskreten Tasks auszuführen, wenn ein Verb als Befehlszeilenargument angegeben wird. Jede Aufgabe wird von einer Klasse behandelt, von denen jede eine Schnittstelle implementiert, die eine Methode Execute() enthält. Ich versuche dies zu tun, ohne if oder switch-Anweisungen zu verwenden. Bisher, was ich habe, ist dies:Gibt es bessere Möglichkeiten, eine zur Laufzeit angegebene Klasse zu instanziieren und eine Methode für diese Instanz aufzurufen?

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

task ist vom Typ IMaintenanceTask, die im Grunde ist das, was ich zu erreichen bin versucht. Ich würde es vorziehen, dynamic zu verwenden - mein Verständnis ist, dass, wenn es nur einmal verwendet wird, wie hier, ich keinen der Vorteile des Caching sehen werde, es nur Reflexion in weniger Tastenanschlägen machen.

Kann dieser Ansatz (oder etwas in der gleichen Richtung) die Leistung merklich beeinträchtigen? Ich weiß, dass es definitiv die Chance von Laufzeitausnahmen/Bugs erhöht, aber das wird teilweise durch die Tatsache gemildert, dass diese Anwendung nur über Skripte ausgeführt wird; es wird nur mit vorhersagbaren Eingaben umgehen - auch dies ist der einzige Ort im Code, der sich dynamisch verhält. Was versuche ich sinnvoll zu erreichen? Oder wäre es besser, einfach das langweilig normale Weise zu tun, indem Sie einfach die Eingabe einschalten und jeden Typ von Aufgabe über einen normalen Konstruktor der Kompilierzeit konstruieren und .Execute() darauf aufrufen.

Antwort

1

Da es nur einmal anrufen, können Sie mit Ihrer Lösung gehen. Fügen Sie einige Bedingungen hinzu, um Ausnahmechancen zu vermeiden.

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(); 
} 
+0

'IsAssignableFrom()' ist die genaue Funktion, die ich musste wissen, über mich bequem mit diesem Code zu machen, ich denke, – Toadfish

+0

Wenn Sie Befehle verwenden zu häufig gehen, können Sie leicht die Instanzen in 'Dictionary-Cache ' –

1

Mach dir keine Sorgen über die Leistung eines Versandmechanismus, es sei denn, es ist in einer engen Schleife. Das Wechseln eines einzelnen direkten Methodenaufrufs zu einem einzelnen Anruf über dynamic, ein einzelner Aufruf durch Reflektion, ein einzelner Aufruf über die Emit-API oder ein einzelner Aufruf durch den kompilierten LINQ-Ausdruck macht keinen erkennbaren Unterschied in der Ausführungszeit Ihrer Anwendung. Die Zeit, die das Betriebssystem benötigt, um Ihre Anwendung zu starten, ist um mehrere Größenordnungen höher als die Zeit, die Ihre Anwendung benötigt, um zu entscheiden, welche Methode Sie aufrufen möchten, also ist Ihre Lösung so gut wie eine switch, außer es ist viel kürzer (was ist eine gute Sache).

Verwandte Themen