Unity容器-将动态DbContext依赖注入服务 [英] Unity Container - Dependency Injection of Dynamic DbContext into Service

查看:108
本文介绍了Unity容器-将动态DbContext依赖注入服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建.Net Web API,该API使用带有实体框架的Service + Repository模式。每个控制器的CRUD操作都会中继通过调用服务检索到的数据。

I'm building a .Net Web API which uses a Service+Repository pattern w/ Entity Framework. Each controller's CRUD actions relay data retrieved by calls to a Service.

我有一个SomeContext扩展了DbContext:

I have a SomeContext that extends DbContext:

public class SomeContext : DbContext
{
    public SomeContext(string connString) : base(connString) { }

    // DbSets
    ...
}

该服务使用构造函数初始化,该构造函数接受ISomeContext:

The Service is initialized w/ a constructor that accepts an ISomeContext:

public class Service : IService
{
    public Service(ISomeContext ctx) : base(ctx)
    {
        _alpha = new AlphaRepository(ctx);
        ...
    }

    GetAllAlpha()
    {
        return _alpha.Get();
    }
    ...
}

我要使用(统一容器)依赖注入,将SomeContext的实例注入到Service构造函数中。给定SomeContext的生命周期应该是API请求的持续时间。困难之处在于SomeContext的连接字符串是动态的,只有在作为API请求的一部分提供运行时参数 client后才能知道。

I want to use (Unity Container) Dependency Injection to inject an instance of SomeContext into the Service constructor. The life cycle of a given SomeContext should be the duration of the API request. The difficulty is that the connection string for SomeContext is dynamic and cannot be known until a runtime parameter 'client' is provided as part of the API request.

此外,还有不确定数量的客户端,因此由于我的每个租户数据库环境,连接字符串也是如此。因此,我不能仅仅基于'client'参数注册 n 已知的SomeContexts和Resolve()。

Furthermore, there are an indeterminate number of clients and therefore connection strings due to my database-per-tenant environment. As such, I cannot just register n known SomeContexts and Resolve() based on the 'client' parameter.

而是内部开发的NuGet带有暴露的ContextFactory的程序包使我可以为客户端检索适当的SomeContext:

Instead, an internally developed NuGet package w/ exposed ContextFactory lets me retrieve the appropriate SomeContext for a client:

ContextFactory.GetClientContext(client);

如何以及在哪里配置Unity Container来管理此动态SomeContext?

How and where do I configure Unity Container to manage this dynamic SomeContext?

附加说明:


  • Unity已经依赖于将IService服务注入到我的控制器的每个
    中动作。因此,在我创建的任何Web API ActionFilter之前,必须先执行Service构造函数
    。这意味着我在注入之前无法识别客户 ...我想这意味着我需要使用工厂和/或委托...?

  • 我'我已经阅读了有关将抽象工厂与DbContext的委托,公共委托IDbContext CreateDbContext(string client); 以及NuGet
    包的GetClientContext的适配器结合使用的信息请求,但我无法将
    全部整合到一个可行的解决方案中。

  • Unity is already dependency injecting the IService Service into each of my Controller actions. Because of this, the Service constructor is executed prior to any of the Web API ActionFilters I have created. This means I can't identify the 'client' prior to the injection...I presume this means I would need to use a factory and/or delegate...?
  • I've read about using an abstract factory in conjunction with a delegate for the DbContext, public delegate IDbContext CreateDbContext(string client);, and adapter for the NuGet package's GetClientContext request, but I haven't been able to piece it all together into a working solution.

感谢您的帮助!

推荐答案

将运行时参数合并到Unity Dependency Injected对象中的技巧是 InjectionFactory

The trick to incorporate runtime parameters into a Unity Dependency Injected object is InjectionFactory:

container.RegisterType<ISomeContext>(
    new PerRequestLifetimeManager(),
    new InjectionFactory(_ => ContextFactoryAdapter.GetSomeContext(new HttpContextWrapper(HttpContext.Current)))
);




InjectionFactory 让您指定容器将用来创建对象的工厂方法

InjectionFactory lets you specify a factory method the container will use to create the object

在这种情况下,我指定了静态ContextFactoryAdapter.GetSomeContext()根据提供的HttpContextWrapper参数中可用数据返回动态SomeContext的方法:

In this case, I designate the static ContextFactoryAdapter.GetSomeContext() method to return a dynamic SomeContext according to data available in the supplied HttpContextWrapper argument:

public static SomeContext GetSomeContext(HttpContextWrapper requestWrapper)
{
    var client = requestWrapper.Request.QueryString["client"];

    return ContextFactory.GetClientContext(client);
}

因此,Unity会将ISomeContext类型解析为GetClientContext()返回的SomeContext。

So, Unity will resolve ISomeContext type to the SomeContext returned by GetClientContext().

RegisterType()的 PerRequestLifetimeManager()参数指示Unity在a的生存期内使用返回的SomeContext实例。单个HTTP请求。为了使Unity自动处理该实例,您还必须在UnityMvcActivator.cs中注册UnityPerRequestHttpModule

The PerRequestLifetimeManager() argument to RegisterType() instructs Unity to use the returned SomeContext instance for the lifetime of a single HTTP request. For Unity to dispose of the instance automatically, you must also also register the UnityPerRequestHttpModule in UnityMvcActivator.cs:

DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));

有了这些配置,Unity就能解析适当的SomeContext并将该实例提供给Service通过构造函数注入。

With these configurations in place, Unity is able to resolve an appropriate SomeContext and supply this instance to the Service via constructor injection.

这篇关于Unity容器-将动态DbContext依赖注入服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆