2017-09-01 5 views
0

Pour clarifier: Au lieu d'utiliser enums, où enum indique la méthode à utiliser, j'utilise des classes dérivées de la même classe de base. Ainsi, au lieu de sélectionner une méthode utilisant enum, l'utilisateur sélectionnera une classe qu'il veut utiliser (via une interface déroulante), et la classe contiendra une substitution de la méthode qui sera appelée. Après l'avoir fait fonctionner comme indiqué ci-dessous j'ai essayé de regarder en ligne pour voir si je le fais bien. C'est une méthode qui résout beaucoup de problèmes, mais mon problème est que je ne connais pas la terminologie pour la décrire et pour vérifier si elle peut causer de sérieux problèmes à l'avenir. Avant d'utiliser Enums pour sélectionner un outil que je veux utiliser (enum tool {brush, gomme, drag}). Mais pour rendre tout plus efficace au lieu d'utiliser Enum, je crée maintenant une classe pour chaque outil qui dérive de la classe de base "ToolType". Ensuite, j'utilise la réflexion pour trouver toutes les classes qui héritent de ToolType et les placer dans un tableau statique. Et maintenant j'utilise cette méthode pour la plupart des choses dans mon projet, il est facile d'ajouter/supprimer des choses, pas besoin d'éditer une matrice enum chaque fois que vous ajoutez une nouvelle classe. Cela ressemble à la meilleure solution pour un projet modulaire, mais je n'ai pas encore trouvé d'exemples de cela, alors je ne suis pas sûr de le faire de la bonne façon. Que devrais-je rechercher?Meilleure façon d'implémenter le sélecteur de classes

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

C'est le constructeur de

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

Je peux avoir

public class newToolBase : Family<newToolBase> { 

}

gomme à effacer public class: newToolBase {

}

crayon public class: newToolBase {

}

J'utilise l'unité et ce que je veux dire par « sélection » est l'option généralement de sélectionner manuellement quelque chose dans un menu déroulant. Comme vous voyez la classe de base a un tableau de noms et ils sont affichés lorsque l'utilisateur sélectionne quelque chose. Chaque objet spawnable, chaque méthode AI utilise cette classe. Je viens d'ajouter un script dérivé de la classe de base qui à son tour dérive de la classe famille et il peut être sélectionné ou ajouté à une liste.

De commentaires ci-dessous j'ai découvert sur l'injection de dépendances et en cours de lecture à ce sujet. J'ai écrit ceci dans l'espoir que les gens reconnaîtront immédiatement ce que j'essaie de faire et montreront quelque chose comme ça.

Pour clarifier, il n'y a pas de problème évident avec mon approche mais avant de passer des heures à remplacer beaucoup d'enums avec ceci je veux m'assurer. Merci.

+4

Utilisez-vous l'injection de dépendance? par exemple. 'Unity',' MEF', 'Ninject' – Nova

+0

Contre-indication: Que faire si vous avez besoin d'un deuxième ensemble de ToolTypes? Un que vous ne voulez pas être sélectionnable, où le premier ensemble est ... – Fildor

+0

Il semble que vous demandiez un [modèle] (http://www.dofactory.com/net/design-patterns), pourtant vous n'avez pas montré quel est le problème. Sélecteur? Par quoi? Par clé - dictionnaire, par index - collection ... Aussi quel est le critère de pourquoi la méthode actuelle est mauvaise? Seulement des doutes? Dites à tout le monde d'aller en enfer, vous êtes le programmeur, c'est votre tâche ... – Sinatr

Répondre

1

J'ai une idée de ce que vous pourriez faire. Il y a probablement de meilleures façons de le faire mais j'espère pouvoir vous donner un coup de pouce dans une direction.

MEF Stands pour Managed Extensibility Framework -

Le cadre Extensibilité géré ou MEF est une bibliothèque pour créer des applications légères et extensibles. MEF

Pour obtenir cette configuration est assez simple, vous devez ajouter la bibliothèque System.ComponentModel.Composition à votre projet.J'ai utilisé une application de console pour démontrer votre cas d'utilisation. Vous devez d'abord initialiser le conteneur MEF.

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); 
    } 
} 

Maintenant que nous avons la configuration de classe de conteneur, vous devez configurer vos classes d'outils.

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"); 
    } 
} 

Maintenant, il est l'utilisation dans une application de la console:

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

Je suppose que vous pouvez extrapoler à partir des exemples ci-dessus et appliquer votre propre logique propre. Ce qui précède peut être simplement collé dans une application de console et devrait fonctionner. N'oubliez pas d'ajouter les références correctes.

Cela aidera à créer une application assez modulaire qui aidera à la maintenabilité et l'extensibilité. Il existe d'autres alternatives d'injection de dépendances, tout dépend de ce dont vous avez besoin.

Espérons que cela aide.

En plus: Pour prolonger cela, il vous suffit d'initialiser le conteneur MEF une fois pour qu'il soit utilisé tout au long du projet. je ToolTypes = mefContainer.Container.GetExportedValues<ToolType>().ToList(); Mais vous pouvez utiliser

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

ou s'il n'y a qu'un seul

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