2017-05-02 6 views
2

Ich möchte über die beste Methode (in C#) zu instanziieren ein Objekt basierend auf einer Eingabezeichenfolge diskutieren. Lassen Sie mich erklären. Let'say Ich habe eine Basisklasse:Der beste Ansatz, um Objekt basierend auf String zu instanziieren

public abstract class BaseCar 
{ 
    public asbtract int GetEngineID(); 
    //Other stuff... 
} 

Dann habe ich mehrere Implementierungen dieser Klasse, sagen wir mal:

public class SportCar : BaseCar 
{ 
    public override int GetEngine() 
    { 
     //Specific implementation 
    } 

} 

public class OtherCar: BaseCar 
{ 
    public override int GetEngine() 
    { 
     //Specific implementation 
    } 

} 

Und so weiter ...

Was würde ich zu tun ist, eine statische CarFactory-Klasse zu machen, die eine CreateCar-Methode hat, die einen string als einen Parameter annimmt und eine BaseCar -Instanz zurückgibt, abhängig davon, welche Zeichenfolge Sie geben. Die Zeichenfolge wäre ein Name einer untergeordneten Klasse.

Zum Beispiel, wenn ich CarFactory.CreateCar('SportCar') aufrufen, sollte es eine SportCar-Instanz zurückgeben.

Ich weiß, dass ich eine einfache switch-Anweisung verwenden könnte zu prüfen, welche Auto angefordert wurde, und erstellen Sie eine neue Instanz auf dem basiert, aber ich mag diesen Ansatz aus zwei Gründen nicht:

  • Ich plane haben eine Menge von Kind Klassen, hard-coding alle case wäre nicht zu einfach zu pflegen
  • Ich plane, eine Inizialisierungsprozedur zu implementieren, um auch einige anfängliche Werte zu den Objekten, die ich erstelle (mit Reflection), so hart-Codierung zu mischen und Reflexion scheint mir keine gute Idee zu sein.

Was ich dachte, ist die Assembly.CreateInstance von System.Reflection zu verwenden, um eine Instanz der angegebenen Klasse zu erstellen, aber da dies das erste Mal, dass ich dieses Problem nähern, ich weiß nicht, ob es bessere Möglichkeiten gibt das zu tun. Ist das ein gültiger Ansatz?

Wenn man bedenkt, dass die Eingabezeichenfolge von einer XML-Datei kommt, gibt es eine einfachere Methode? Vielleicht wird mein Problem bereits in einigen .NET Assemblies behandelt, die ich vermisse.

+0

https://msdn.microsoft.com/en-us/library/d133hta4(v=vs.110).aspx –

+0

Gleiche Abfrage hier (für Java) ..sollte wahrscheinlich einige Hinweise geben: http://stackoverflow.com/questions/3434466/creating-a-factory-method-in-java-that-doesnt-rely-on-i-el-se – Achilles

Antwort

0

Hier ist, was ich gefunden habe. Eine generische Factory-Klasse, die automatisch alle Typen registriert, die eine Unterklasse des angegebenen Typs sind. Außerdem können Sie sie über ihren Namen instanziieren. Dies hängt etwas mit dem in the Java SO question gezeigten Ansatz zusammen, der durch @Achilles in den Kommentaren verknüpft ist, nur dass dem Typ keine Initialisierungsfunktion zugeordnet ist.

Es ist nicht erforderlich, eine Enum/Switch-Kombination aller Typen beizubehalten. Es sollte auch leicht erweiterbar sein, um Ihre vorgeschlagene reflexionsbasierte Initialisierung zu handhaben.

static class StringFactory<T> where T : class 
{ 
    static private Dictionary<string, Type> s_dKnownTypes = new Dictionary<string, Type>(); 

    static StringFactory() 
    { 
     RegisterAll(); 
    } 

    static private void RegisterAll() 
    { 
     var baseType = typeof(T); 
     foreach (var domainAssembly in AppDomain.CurrentDomain.GetAssemblies()) 
     { 
      foreach (var type in domainAssembly.GetTypes() 
       .Where(t => t.IsSubclassOf(baseType))) 
      { 
       s_dKnownTypes.Add(type.Name, type); 
      } 
     } 
    } 

    static public T Create(string _sTypeName) 
    { 
     Type knownType; 
     if (s_dKnownTypes.TryGetValue(_sTypeName, out knownType)) 
     { 
      return (T)Activator.CreateInstance(knownType); 
     } 

     throw new KeyNotFoundException(); 
    } 
} 

die Klassen Ihrer Frage Unter der Annahme bestehen, würden Sie ein bestimmtes Auto wie dieses instanziiert:

var car = StringFactory<BaseCar>.Create("SportsCar"); 
DoSomethingWith(car.EngineID()); 

Da Ihre Frage für eine Diskussion über die besten Ansätze war, beachten Sie bitte diese nur eine von ihnen . Ich habe dies in einer Produktionsumgebung nicht verwendet, und es ist durchaus möglich, dass dies der falsche Ansatz für Ihre spezifische Situation ist. Es funktioniert jedoch gut genug, um das allgemeine Prinzip aufzuzeigen, und sollte einen Ausgangspunkt für weitere Diskussionen bieten.

+0

Vielen Dank für diese Idee, eigentlich ich Denken Sie daran, alle verfügbaren Typen einmal zu registrieren und dann eine Datenstruktur zu verwenden, um sie zuzuordnen, ist ein guter Ansatz, anstatt nach dem angegebenen Typ in der Assembly zu suchen, jedes Mal, wenn eine Instanz erneut angefordert wird. – Andrew

Verwandte Themen