0

Cela me déroute, donc cette question sera probablement confuse.Comment pouvez-vous mapper génériquement un DbDataReader à un type résolu Castle.Windsor?

J'ai une application qui utilise des implémentations d'une interface IJob pour accomplir différentes tâches.

public interface IJob 
{ 
    int Id { get; set; } 
    string Name { get; set; } 
    void Run(); 
} 

Je me sers du Castle.Windsor.WindsorContainer pour résoudre ces mises en œuvre, et en utilisant l'identifiant de service pour les aider à identifier. J'ai écrit une petite méthode d'extension générique qui met simplement les valeurs des colonnes SQL dans leurs propriétés correspondantes. Maintenant, parce que vous ne pouvez pas instancier une instance d'une interface, le passage d'un IJob à cette méthode ne fonctionnera pas. Cependant, pour bénéficier des avantages du conteneur IoC, j'ai besoin de tout faire dans mon référentiel en utilisant l'interface IJob. Alors, je l'ai écrit avec cela pour résoudre la mise en œuvre de ijob, et le transmettre à la méthode MapTo pour remplir les propriétés nécessaires:

public IJob GetJobById(int id) 
    { 
     string cmdTxt = "SELECT Id, Name, Description, DateStarted, ScheduledCompletion, Completed FROM Jobs WHERE Id = @id"; 

     using (DbCommand cmd = _dataFactory.CreateCommand(cmdTxt)) 
     { 
      _dataFactory.AddParam(cmd, "id", id, DbType.Int32); 
      using (DbDataReader rdr = cmd.ExecuteReader()) 
      { 
       if (rdr.Read()) 
       { 
        IJob job = _container.Resolve<IJob>("job.implementation"); 
        rdr.MapTo<IJob>(ref job); 
        return job; 
       } 
       else 
       { 
        return null; 
       } 
      } 
     } 
    } 

Est-ce une décision de conception OK? Voyez-vous des problèmes?

+0

Ces tâches planifiées s'exécutent-elles à un moment donné de la journée? Si c'est le cas, vous pouvez regarder Caslte.Schedular, il vous donnera un cadre pour créer et gérer des emplois et vous permettre de penser à la façon dont les emplois fonctionnent. Aussi comme il fait partie du château il s'intégrera bien avec windsor. – pythonandchips

+0

Castle.Scheduler est sur le point de devenir obsolète –

+0

@Colin, ils ne sont pas programmés. Plus comme, nous devons exécuter ce script sur 1000 machines, ou nous avons besoin de ce fichier de configuration tiré de tous les systèmes qui correspondent à tel ou tel critère. Ils sont généralement juste une affaire unique. – scottm

Répondre

1

Eh bien, pour l'un, l'appel de méthodes via la réflexion est généralement pas agréable ... et il semble que vous utilisez Windsor comme un dictionnaire de type, ce qui est pas ...

Je voudrais écrire un non -generic (qui prendra un Type comme paramètre) qui fonctionne sur une instance déjà existante (lorsque vous créez une nouvelle instance avec Activator.CreateInstance vous supprimez l'instance que Windsor a résolue) et l'utilisez ensuite à partir de l'événement ComponentCreatedEvent dans IKernel. Quelque chose comme ceci:

container.Kernel.ComponentCreated += (model, instance) => { 
    if (model.Service == typeof(IJob)) { 
    // select id,name from jobs where id = model.Name 
    // use MapTo to fill id,name into instance 
    } 
} 
+0

J'ai remarqué que je gaspillais l'instance que Windsor a résolu (qui est l'un des raison pour laquelle j'ai posté ici). Le problème que j'éprouvais était le suivant: Si je crée une méthode MapTo non générique, je devrais en créer un pour chaque objet de domaine (un qui mappe Job, un qui mappe le résultat, etc.) et les place dans le référentiels respectifs? J'ai édité les méthodes MapTo et GetJobById d'une manière qui n'élimine pas l'instance résolue de Windsor. Quelles sont vos pensées? – scottm

+0

Vous n'avez pas besoin d'écrire plusieurs méthodes MapTo. Vous pouvez obtenir le type à partir de instance.GetType() au lieu de typeof (T). Le reste est le même. –

+0

ouais, je pense que je l'ai compris, donc je n'ai pas à le faire. – scottm