Injectez la même instance DataContext sur plusieurs types avec Unity

Supposons que je possède une interface IRepository et son implémentation SqlRepository qui prend comme argument LINQ to SQL DataContext. Supposons également que j’ai l’interface IService et ses services d’implémentation qui prennent trois référentiels IR, IRepository et IRepository. Le code de démonstration est ci-dessous:

public interface IRepository { } public class SqlRepository : IRepository { public SqlRepository(DataContext dc) { ... } } public interface IService { } public class Service : IService { public Service(IRepository r1, IRepository, IRepository) { ... } } 

Est-il possible, lors de la création de la classe Service, d’injecter le même DataContext aux trois référentiels?

Tout ce que vous avez à faire est de vous assurer que, lorsque vous enregistrez le Datacontext dans votre conteneur Unity, utilisez PerResolveLifetimeManager dans config:

    

ou en code:

 container.RegisterType(new PerResolveLifetimeManager()); 

puis, chaque fois que le conteneur résout le Service les dépendances nécessitant également un DataContext reçoivent exactement le même. Mais la prochaine demande de résolution du Service créera un nouveau DataContext .

Je pense que je sais ce que tu veux faire. Je suis dans le même bateau et j’essaie de trouver une solution.

Ma couche Service effectue des opérations sur les demandes à venir, et son action dépend du contenu. Il passe à une série de chaînes de responsabilité. Je veux que le même contexte soit transmis à toutes les classes pendant la durée de vie de la méthode de service appelée

Vous pouvez spécifier PerResolveLifetimeManager. Jusqu’à présent, il semble fonctionner avec mes cas de test:

Classe de service:

 public interface IServiceClass { void DoService(); } class ServiceClass : IServiceClass { private IHandler Handler { get; set; } public ServiceClass(IHandler handler) { Handler = handler; } public void DoService() { Handler.HandleRequest(); } } 

IHandler est implémenté par deux classes et exécute un modèle de chaîne de responsabilité:

  public interface IHandler { void HandleRequest(); } class Handler : IHandler { private IDataContext DataContext { get; set; } public Handler(IDataContext dataContext) { DataContext = dataContext; } public void HandleRequest() { DataContext.Save("From Handler 1"); } } class Handler2 : IHandler { private IDataContext DataContext { get; set; } private IHandler NextHandler { get; set; } public Handler2(IDataContext dataContext, IHandler handler) { DataContext = dataContext; NextHandler = handler; } public void HandleRequest() { if (NextHandler != null) NextHandler.HandleRequest(); DataContext.Save("From Handler 2"); } } 

Comme vous pouvez le constater, les deux gestionnaires acceptent une instance de IDataContext, que je souhaite être identique dans les deux cas. Handler2 accepte également une instance de IHandler à laquelle passer le contrôle (il fait ici la démonstration à la fois, mais en réalité, un seul gérerait la requête …)

IDataContext. Dans le constructeur, j’initialise un Guid et, lors de son fonctionnement, le génère afin que je puisse voir si les deux fois où l’appelé utilise la même instance:

 public interface IDataContext { void Save(ssortingng fromHandler); } class DataContext : IDataContext { private readonly Guid _guid; public DataContext() { _guid = Guid.NewGuid(); } public void Save(ssortingng fromHandler) { Console.Out.WriteLine("GUI: [{0}] {1}", _guid, fromHandler); } } 

Enfin, enregistrement et appel du service:

  private IUnityContainer container; private void InitializeUnity() { container = new UnityContainer(); container.RegisterType("Handler2", new InjectionConstructor(new ResolvedParameter(), new ResolvedParameter("Handler1"))); container.RegisterType("Handler1"); container.RegisterType(new PerResolveLifetimeManager()); container.RegisterType("MyClass", new InjectionConstructor(new ResolvedParameter("Handler2"))); } private void CallService() { var service = container.Resolve("MyClass"); service.DoService(); // Resolving and calling again to simulate multiple resolves: service = container.Resolve("MyClass"); service.DoService(); } 

Voici le résultat obtenu:

 GUI: [f2250055-8a5f-4f80-a1b6-bcc5574138cf] From Handler 1 GUI: [f2250055-8a5f-4f80-a1b6-bcc5574138cf] From Handler 2 GUI: [22a5c0a3-3c5c-4683-807d-bf2b43f3cd0a] From Handler 1 GUI: [22a5c0a3-3c5c-4683-807d-bf2b43f3cd0a] From Handler 2 

J’espère que ce mur de texte a répondu à votre question … Sinon, cela m’a inspiré une solution que je devais mettre en œuvre …

Si je comprends bien votre question (et si vous utilisez l’unité … je suppose que vous le faites parce que vous l’avez étiquetée avec l’unité), vous pouvez faire quelque chose comme ceci:

Dans vos implémentations de référentiel,

 [InjectionConstructor] public SqlRepository( [Dependency] DataContext ctx) 

mais vous devez ensuite marquer le constructeur de services de la même manière et utiliser le conteneur pour résoudre vos services ainsi que le référentiel. Le DataContext doit également être dans le conteneur pour le faire fonctionner.

Une approche alternative consiste à faire quelque chose comme ceci avec votre référentiel:

 [InjectionMethod] public void Initialize( [Dependency] DataContext ctx 

cela dira à l’unité d’appeler cette méthode si, dans le constructeur de votre service, vous utilisez l’unité avec la méthode BuildUp … à peu près comme ceci:

 unitycontainer.BuildUp(repository); 

Je suppose que ce n’est pas tout à fait ce que vous cherchez, mais dites-moi s’il vous plaît si je suis sur la bonne voie et je verrai si je peux vous aider plus loin …

Cheers / J

Avez-vous essayé d’utiliser la méthode RegisterInstance () pour le conteneur d’unité? Quelque chose comme ça pourrait marcher:

UnityContainer statique public CreateContainer () {conteneur UnityContainer = new UnityContainer ();

  try { var section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection; if (section != null) { section.Containers[0].Configure(container); } } catch (Exception ex) { TraceLogger.LogMessage("Configurarion Error for Unity Container", ex.Message, TraceEventType.Critical); Environment.Exit(1); } container.RegisterInstance(new DataContext()); return container; } 

Désormais, chaque fois que ce conteneur tente de générer un object nécessitant un DataContext, la même instance est transmise. Vous pouvez même configurer le DataContext avant d’enregistrer son instance.

MISE À JOUR: Une option (maintenant, je ne sais pas si c’est vraiment une bonne pratique, mais cela a fonctionné pour moi) est de créer un conteneur différent pour chaque object que vous allez créer. Quelque chose comme:

 UnityContainer container1 = ContainerFactory.CreateContainer(); UnityContainer container2 = ContainerFactory.CreateContainer(); UnityContainer container3 = ContainerFactory.CreateContainer(); MyObject1 object1 = container1.Resolve(); MyObject2 object2 = container2.Resolve(); MyObject3 object3 = container3.Resolve(); 

ou d’une manière plus résumée:

 MyObject1 object1 = ContainerFactory.CreateContainer().Resolve(); MyObject1 object2 = ContainerFactory.CreateContainer().Resolve(); MyObject1 object3 = ContainerFactory.CreateContainer().Resolve(); 

Eh bien, il y a beaucoup de façons de le faire, créer une liste, en utilisant le modèle d’usine. J’espère que ça aide