2017-05-23 1 views
0

J'utilise C#, WPF, Prism 6.3 et j'utilise Unity comme conteneur IoC.Comment créer une classe à partir d'une chaîne, enregistrer puis résoudre à l'aide de l'unité

Voici une partie que je ne comprends pas très bien et qui pourrait être plus claire. Scénario: Mon application communique avec plusieurs lasers physiques. J'ai créé un LaserModule avec Views/Viewmodels, ainsi que l'interface ILaser, et 3 classes laser spécifiques à la marque (LaserA/B/C). Comme tous les lasers ont la même fonctionnalité (Connect, GetReading, Disconnect), j'ai pensé que c'était une bonne idée de faire l'interface ILaser, donc ils doivent tous implémenter ces méthodes, mais de toutes les manières dont ils ont besoin. En outre, le module lira à partir d'un fichier laser.cfg et dans ce fichier il aura les paramètres pour chaque laser, y compris la "Classe" du laser que je vais utiliser pour instancier la classe laser appropriée avec. L'idée générale est que le LaserModule créera de nombreux lasers dans le fichier de configuration, du type approprié, puis les enregistrera dans un conteneur unitaire afin qu'ils puissent accéder à d'autres parties de l'application. Dans les autres parties de mon application, le but est que le programmeur n'ait pas besoin de savoir quoi que ce soit au sujet du laser ou de la classe spécifique, au lieu de travailler avec l'interface. Les interfaces seront toutes stockées dans un module commun, ce qui devrait être la seule dépendance.

C'est où je suis maintenant ... et il semble fonctionner parce que quand les méthodes .Greet() sont appelées à la fin, je vois le message d'accueil que j'ai donné en utilisant Activator.CreateInstance.

Est-ce que cette approche est réaliste ou est-ce que je manque complètement le point?

namespace LaserModule 
{ 
    interface ILaser 
    { 
     void Greet(); 
    } 
} 


namespace LaserModule 
{ 
    class LaserA: ILaser 
    { 

     private string greeting = "blank"; 

     public LaserA(string greet) 
     { 
      this.greeting = greet; 
     } 

     public void Greet() 
     { 
      MessageBox.Show("LaserA - " + greeting); 
     } 
    } 
} 

public void Initialize() 
{ 

    //Create Laser objects based on what brand of laser is supplied 
    String className = ReadLaserClassNameFunc1(); 
    Type t = Type.GetType("LaserModule." + className, true); 
    object t2 = (Activator.CreateInstance(t,"laser 1 greeting")); 
    ILaser myLaser1 = (ILaser)t2; 

    //Create Laser objects based on what brand of laser is supplied 
    className = ReadLaserClassNameFunc2(); 
    t = Type.GetType("LaserModule." + className, true); 
    t2 = (Activator.CreateInstance(t,"laser 2 greeting")); 
    ILaser myLaser2 = (ILaser)t2; 

    //Create Laser objects based on what brand of laser is supplied 
    className = ReadLaserClassNameFunc3(); 
    t = Type.GetType("LaserModule." + className, true); 
    t2 = (Activator.CreateInstance(t,"laser 3 greeting")); 
    ILaser myLaser3 = (ILaser)t2; 


    _unityContainer.RegisterInstance("Laser1", myLaser1, new ContainerControlledLifetimeManager()); 
    _unityContainer.RegisterInstance("Laser2", myLaser2, new ContainerControlledLifetimeManager()); 
    _unityContainer.RegisterInstance("Laser3", myLaser3, new ContainerControlledLifetimeManager()); 

    ... 
    //The following lines would in reality be called from a different assembly. 

    ILaser theLaser1 = _unityContainer.Resolve<ILaser>("Laser1"); 
    ILaser theLaser2 = _unityContainer.Resolve<ILaser>("Laser2"); 
    ILaser theLaser3 = _unityContainer.Resolve<ILaser>("Laser3"); 

    theLaser1.Greet(); 
    theLaser2.Greet(); 
    theLaser3.Greet(); 

} 

Mise à jour: interfaces ont été ajoutées et services ...

ILaserService.cs

using System.Collections.Generic; 

namespace xxx.Infrastructure.Interfaces 
{ 
    public interface ILaserService 
    { 
     void CreateLasers(); 
     List<ILaser> GetLasers(); 

    } 
} 

LaserService.cs

using xxx.Infrastructure.Interfaces; 
using System; 
using System.Collections.Generic; 
using System.Windows; 

namespace LaserModule 
{ 
    public class LaserService : ILaserService 
    { 
     readonly List<ILaser> _lasers = new List<ILaser>(); 

     public LaserService() 
     {    
     } 

     public void CreateLasers() 
     { 

      //Create Laser objects based on config file 

      string nameSpace= GetType().Namespace; 

      string className = "LaserA"; 
      Type t = Type.GetType(nameSpace + "." + className, true); 
      object t2 = (Activator.CreateInstance(t, "laser 1 greeting")); 
      _lasers.Add((ILaser)t2); 

      className = "LaserB"; 
      t = Type.GetType(nameSpace + "." + className, true); 
      t2 = (Activator.CreateInstance(t, "laser 2 greeting")); 
      _lasers.Add((ILaser)t2); 

      className = "LaserC"; 
      t = Type.GetType(nameSpace + "." + className, true); 
      t2 = (Activator.CreateInstance(t, "laser 3 greeting")); 
      _lasers.Add((ILaser)t2); 


     } 

     public List<ILaser> GetLasers() 
     { 
      return _lasers; 
     } 

    } 
} 

LaserModule.cs

using Microsoft.Practices.Unity; 
using Prism.Modularity; 
using Prism.Regions; 
using Prism.Unity; 
using System.Windows; 
using System; 
using xxx.Infrastructure.Constants; 
using xxx.Infrastructure.Interfaces; 
using System.Collections.Generic; 

namespace LaserModule 
{ 
    { 
    public class LaserModule : IModule 
    { 
     private readonly IRegionManager _regionManager; 
     private readonly IUnityContainer _unityContainer; 

     public LaserModule(IRegionManager regionManager, IUnityContainer unityContainer) 
     { 
      _regionManager = regionManager; 
      _unityContainer = unityContainer; 
     } 

     public void Initialize() 
     { 

      //Create and register instance of laser service 
      _unityContainer.RegisterInstance(typeof(ILaserService), _unityContainer.Resolve<LaserService>(),new ContainerControlledLifetimeManager()); 

      //Pull instance out of container 
      ILaserService myLaserService = _unityContainer.Resolve<ILaserService>(); 
      myLaserService.CreateLasers(); 

      List<ILaser> myLasers = myLaserService.GetLasers(); 

      MessageBox.Show("LaserModule Ref Hash:" + myLasers.GetHashCode().ToString()); 

      //Connect and display feedback 

      bool allOK = true; 

      foreach (ILaser _laser in myLasers) 
      { 
       if (_laser.Connect() == false) 
       { 
        allOK = false; 
       } 
      } 

      if (allOK == true) 
      { 
       _regionManager.RegisterViewWithRegion(RegionNames.RightSideRegion, typeof(Views.LaserModuleUI1)); 
       _regionManager.RegisterViewWithRegion(RegionNames.RightSideRegion, typeof(Views.LaserModuleUI2)); 
      }else 
      { 
       MessageBox.Show("1 or more lasers failed"); 
      } 


     } 
    } 
} 

Bootstrapper.cs InitializeModules()

protected override void InitializeModules() 
    { 

     // Initialize Modules 
     base.InitializeModules(); 

     ILaserService myLaserService = Container.Resolve<ILaserService>(); 

     List<ILaser> myLasers = myLaserService.GetLasers(); 

     MessageBox.Show("Bootstrap Ref Hash:" + myLasers.GetHashCode().ToString()); 

    } 

Alors que mon ILaser et ILaserService sont dans mon projet d'infrastructure, de sorte que le Shell et LaserModule dépendent de l'infrastructure, mais pas. Je vérifie le code Hashcode lorsque je crée les lasers dans LaserModule, ainsi que quand ils sont retirés du conteneur dans le bootstrapper et ils correspondent tous les deux.

Le bootstrapper n'aura pas besoin des lasers (d'autres modules le seront) mais pour preuve de concept je pense que je fais les choses correctement. Un aperçu?

Répondre

0

Pourquoi ne pas simplement avoir un ILaserService qui maintient les lasers dans votre application? Ensuite, vous pouvez résoudre le ILaserSerrvice et lui demander le laser qui vous intéresse.

Exemple:

ILaser laser = _laserService.GetLaser (Lasers.LaserOne);

+0

Cela semble être une bien meilleure approche, mais je n'ai aucune expérience de ce genre. Y a-t-il une chance que vous puissiez me diriger dans une certaine direction concernant l'utilisation de «services» de cette manière? C'est juste difficile de google quelque chose quand je ne suis même pas familier avec le verbiage. En ce qui concerne ma création de lasers à l'aide d'Activator, y a-t-il un problème si le code doit créer dynamiquement des classes à partir d'un fichier de configuration? Merci encore d'avoir pris le temps de répondre – z0nghits

+0

Activator semble un peu northadox, mais si ça marche pour vous, alors allez-y. Créez simplement une classe appelée LaserService qui implémente votre interface ILaserService. Ensuite, mettez toute votre logique pour les chargements, vous lasers là-bas. Enregistrez votre service en tant que singleton avec le conteneur et vous êtes prêt. –