使用Unity在多个类型中注入相同的DataContext实例

假设我有IRepository接口及其实现SqlRepository,它将LINQ作为参数作为SQL DataContext的参数。 假设我有IService接口及其实现服务,它需要三个IRepository,IRepository和IRepository。 演示代码如下:

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

在创建Service类以使用相同的DataContext注入所有三个存储库时是否有任何方法?

您需要做的就是确保在您的Unity容器中注册Datacontext ,请在config中使用PerResolveLifetimeManager

    

或在代码中:

 container.RegisterType(new PerResolveLifetimeManager()); 

然后,只要容器解析Service任何依赖于需要DataContext依赖项都将提供完全相同的依赖项。 但是,解决Service的下一个请求将创建一个新的DataContext

我想我知道你想做什么。 我正在同一条船上试图想出一个解决方案。

我的服务层在即将到来的请求中执行操作,它的作用取决于内容。 它将它传递给一系列责任类。 我想在调用的服务方法的生命周期内传递给所有类的相同上下文

您可以指定PerResolveLifetimeManager。 到目前为止,似乎正在处理我的测试用例:

服务类别:

 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由两个类实现,并执行Chain of Responsibility模式:

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

正如您所看到的,两个处理程序都接受IDataContext的实例,我希望它们在两个实例中都是相同的。 Handler2还接受一个I​​Handler实例来传递控制(它在这里做两个演示,但实际上,只有一个会处理请求…)

IDataContext。 在构造函数中,我初始化一个Guid,并在其操作期间输出它,以便我可以看到它被调用的两次是否使用相同的实例:

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

最后,注册和服务呼叫:

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

这是我得到的输出:

 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 

希望这段文字回答你的问题……如果不是抱歉,它确实激发了我需要实施的解决方案……

如果我正确理解你的问题(如果你使用统一…我想你这样做是因为你已经用统一标记了它)你可以这样做:

在您的存储库实现中,

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

但是,您必须以相同的方式标记服务构造函数,并使用容器来解析您的服务以及存储库。 DataContext也必须在容器中才能使其工作。

另一种方法是在您的存储库中执行以下操作:

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

如果您在服务构造函数中使用Unity和BuildUp方法,这将告诉unity调用此方法…类似这样:

 unitycontainer.BuildUp(repository); 

我想这不是你想要的,但请告诉我,如果我走在正确的轨道上,我会看看能不能帮你进一步……

干杯/ J.

您是否尝试过对Unity统一容器使用RegisterInstance()方法? 这样的事情可能有用:

public static UnityContainer CreateContainer(){UnityContainer container = 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; } 

现在,每次此容器尝试构建需要DataContext的对象时,都会传递相同的实例。 您甚至可以在注册其实例之前配置DataContext。

更新:一个选项(现在,我不知道它是否真的是一个很好的做法,但这对我有用)是为你要创建的每个对象创建一个不同的容器。 就像是:

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

或者更总结的方式:

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

好吧,有很多方法可以做到,使用工厂模式创建一个列表。 希望能帮助到你