2017-09-01 5 views
0

Zur Verdeutlichung: Anstatt enums zu verwenden, wo enum angibt, welche Methode verwendet werden soll, verwende ich Klassen, die von der gleichen Basisklasse abgeleitet sind. Anstatt also eine Methode auszuwählen, die enum verwendet, wählt der Benutzer eine Klasse aus, die er verwenden möchte (über die Dropdown-Schnittstelle), und die Klasse enthält eine Überschreibung der Methode, die aufgerufen wird. Nachdem ich es wie unten gezeigt funktionierte, versuchte ich online zu schauen, ob ich es richtig mache. Es ist eine Methode, die viele Probleme löst, aber mein Problem ist, dass ich keine Terminologie kenne, um es zu beschreiben und zu prüfen, ob es in der Zukunft ernsthafte Probleme verursachen kann.Die beste Methode zum Implementieren des Klassenselektors

Bevor ich Enums verwenden würde, um ein Werkzeug zu wählen, das ich verwenden möchte (enum tool {Pinsel, Radiergummi, ziehen}). Aber um alles effizienter zu machen, anstatt Enum zu verwenden, erstelle ich jetzt eine Klasse für jedes Werkzeug, das von der Basisklasse "ToolType" abgeleitet ist. Dann verwende ich Reflektion, um alle Klassen zu finden, die von ToolType erben, und sie in einem statischen Array zu platzieren. Und jetzt benutze ich diese Methode für die meisten Dinge in meinem Projekt, es ist einfach Dinge hinzuzufügen/zu entfernen, es ist nicht nötig jedes Enum-Array zu bearbeiten, wenn du eine neue Klasse hinzufügst. Es fühlt sich an wie eine beste Lösung für ein modulares Projekt, aber ich habe noch keine Beispiele dafür gefunden, also bin ich mir nicht sicher, ob ich es richtig mache. Nach was soll ich suchen?

static Family() { 
    List<Type> allTypes = CsharpFuncs.GetAllChildTypesOf<T>(); 

    family = new T[allTypes.Count]; 
    names = new string[allTypes.Count]; 

    Debug.Log("Creating "+typeof(T).ToString()); 

    for (int i = 0; i < allTypes.Count; i++) { 
     Debug.Log("Adding " + allTypes[i].ToString()); 
     T tmp = (T)Activator.CreateInstance(allTypes[i]); 
     family[i] = tmp; 
     tmp.index = i; 
     names[i] = tmp.ToString(); 
    } 
} 

Dies ist der Konstruktor von

public class Family<T> where T : Family<T> 

Dann kann ich

public class newToolBase : Family<newToolBase> { 

}

public class Radiergummi haben: newToolBase {

}

public class Bleistift: newToolBase {

}

Ich bin mit Unity und was ich mit "Auswahl" bedeuten, ist in der Regel Option manuell etwas aus einem Drop-Down wählen. Wie Sie sehen, hat die Basisklasse ein Array von Namen und diese werden angezeigt, wenn der Benutzer etwas auswählt. Jedes spawnbare Objekt, jede KI-Methode verwendet diese Klasse. Ich füge nur ein Skript hinzu, das von der Basisklasse abgeleitet ist, die wiederum von der Familienklasse abgeleitet ist und sie kann ausgewählt oder zu einer Liste hinzugefügt werden.

Von den Kommentaren unten erfuhr ich über Abhängigkeiten Injection und liest gerade darüber. Ich habe dies in der Hoffnung geschrieben, dass die Leute sofort erkennen, was ich versuche, und auf so etwas hinweisen.

Um zu verdeutlichen, gibt es kein offensichtliches Problem mit meinem Ansatz, aber bevor ich Stunden damit verbringe, viele Enums zu ersetzen, möchte ich sicherstellen. Vielen Dank.

+4

Verwenden Sie eine Dependency Injection? z.B. 'Unity',' MEF', 'Ninject' – Nova

+0

Kontraindikation: Was ist, wenn Sie eine zweite Reihe von ToolTypes benötigen? Eines, das du nicht auswählbar sein willst, wo das erste Set ist ... – Fildor

+0

Es klingt, als ob du nach einem [Muster] (http://www.dofactory.com/net/design-patterns) fragst Sie haben nicht gezeigt, was das Problem ist. Wähler? Womit? Nach Schlüssel - Wörterbuch, nach Index - Sammlung ... Auch was ist das Kriterium dafür, warum die aktuelle Methode schlecht ist? Nur Zweifel? Sag jedem, dass er in die Hölle gehen soll, du bist der Programmierer, es ist deine Aufgabe ... – Sinatr

Antwort

1

Ich habe eine Idee für das, was Sie tun könnten. Es gibt wahrscheinlich bessere Möglichkeiten, dies zu tun, aber hoffentlich kann ich Ihnen einen Stoß in eine Richtung geben.

MEF Ständer für Extensibility Framework verwaltet -

Die Managed Extensibility Framework oder MEF ist eine Bibliothek für die Erstellung von leichtgewichtigen, erweiterbare Anwendungen. MEF

dieses Setup zu bekommen ziemlich einfach ist, müssen Sie die System.ComponentModel.Composition Bibliothek zu einem Projekt hinzuzufügen.

Ich habe eine Konsole App verwendet, um Ihren Anwendungsfall zu demonstrieren. Zuerst müssten Sie den MEF-Container initialisieren.

class MefContainer 
{ 
    public CompositionContainer Container { get; } 

    public MefContainer() 
    { 
     var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); // You can use an AggregateCatalog if you have more than one assembly. 

     Container = new CompositionContainer(catalog); 

     Container.ComposeParts(this); 
    } 
} 

Jetzt, wo wir die Container-Klasse-Setup haben, würden Sie up-Klassen Ihr Werkzeug einrichten müssen.

abstract class ToolType // I've used an abstract class here, but you can use interfaces or normal classes. 
{ 
    public virtual void Test() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

[Export(typeof(ToolType)), PartCreationPolicy(CreationPolicy.NonShared)] // Part creation policy is for your lifetime management. NonShared is instanced and Shared would be like a singleton. 
class Brush : ToolType 
{ 
    public override void Test() 
    { 
     Console.WriteLine("Brush"); 
    } 
} 

[Export(typeof(ToolType)), PartCreationPolicy(CreationPolicy.NonShared)] 
class Eraser : ToolType 
{ 
    public override void Test() 
    { 
     Console.WriteLine("Eraser"); 
    } 
} 

[Export(typeof(ToolType)), PartCreationPolicy(CreationPolicy.NonShared)] 
class Drag : ToolType 
{ 
    public override void Test() 
    { 
     Console.WriteLine("Drag"); 
    } 
} 

Jetzt ist es Verwendung in einer Konsole App:

class Program 
{ 
    public static List<ToolType> ToolTypes { get; set; } 

    static void Main(string[] args) 
    { 
     var mefContainer = new MefContainer(); 

     ToolTypes = mefContainer.Container.GetExportedValues<ToolType>().ToList(); 

     ToolTypes.First(x => x.GetType() == typeof(Brush))?.Test(); 
     ToolTypes.First(x => x.GetType() == typeof(Eraser))?.Test(); 
     ToolTypes.First(x => x.GetType() == typeof(Drag))?.Test(); 
    } 
} 

Ich nehme an, Sie aus den obigen Beispielen extrapolieren könnte und Ihre eigene eigene Logik anwenden. Das obige kann einfach in eine Konsolen-App eingefügt werden und sollte funktionieren. Denken Sie daran, die richtigen Referenzen hinzuzufügen.

Dies wird helfen, eine ziemlich modulare App zu erstellen, die bei der Wartbarkeit und Erweiterbarkeit hilft. Es gibt andere Dependency Injektionsalternativen, alles hängt davon ab, was Sie benötigen.

Hoffe, das hilft.

Extra: Um dies weiter zu erweitern, müssen Sie den Container MEF nur einmal initialisieren, damit er während des gesamten Projekts verwendet werden kann. Ich benutzte ToolTypes = mefContainer.Container.GetExportedValues<ToolType>().ToList(); Aber man konnte

[ImportMany(typeof(ToolType))] 
public List<ToolType> ToolTypes { get; set; } 

oder wenn es benutzen, ist nur ein

[Import(typeof(ToolType))] 
public ToolType Tool { get; set; } 
Verwandte Themen