【问题标题】:How to dynamically create and inject services in ASP.NET 5?如何在 ASP.NET 5 中动态创建和注入服务?
【发布时间】:2015-11-17 15:21:47
【问题描述】:

我的情况是,vnext 的 DI 容器的经典功能不足以为我提供正确的功能。假设我有一个 DataService 可以从这样的数据库中获取数据:

public class DataService : IDataService, IDisposable {
  public List<MyObject> GetMyObjects() 
  {
    // do something to fetch the data...
    return myObjects;
  }
}

然后我可以在Startup.cs的配置阶段在DI容器中注册这个服务:

public void ConfigureServices(IServiceCollection services) 
{
  services.AddScoped(typeof(IDataService), typeof(DataService));
}

这确保了服务的正确生命周期(每个请求范围一个),但是,当发出不同的请求时,我需要服务访问不同的数据库。为简单起见,假设适用以下场景:

  • 当向我的 Web API 发出请求时,DataService 将访问当前登录的用户,其中包含一个名为 Database 的声明,其中包含要使用的数据库的信息。
  • DataService 然后使用正确的数据库连接进行实例化。

为了让第二步正常工作,我为 DataService 创建了一个构造函数,如下所示:

public DataService(IHttpContextAccessor accessor) 
{
   // get the information from HttpContext
   var currentUser = accessor.HttpContext.User;
   var databaseClaim = currentUser.Claims.SingleOrDefault(c => c.Type.Equals("Database"));

   if (databaseClaim != null) 
   {
      var databaseId = databaseClaim.Value;
      // and use this information to create the correct database connection
      this.database = new Database(databaseId);
   }
}

通过使用当前登录的用户及其声明,我可以确保我自己的身份验证中间件负责提供必要的信息,以防止攻击者尝试访问错误的数据库。

当然需要添加IDisposable 实现来清理任何数据库连接(并使用范围生命周期正确调用)。

然后我可以将DataService 注入这样的控制器中

public MyController : Controller 
{
   private IDataService dataService;
   public MyController(IDataService dataService) 
   {
     this.dataService = dataService;
   }
}

到目前为止,这一切都很好。 我现在的问题是:

  1. 除了使用DataService 的构造函数之外,还有其他方法可以创建实例吗?也许访问IServiceCollection 在不同位置提供的对象,而不是在只运行一次的配置阶段?也许使用我自己的 OWIN 中间件?
  2. 这种方法真的安全吗?同时发出的两个请求是否会意外地以另一个请求的 DataServiceintended 结尾,从而最终给出错误的数据?

【问题讨论】:

  • 如何创建一个工厂,根据某些参数为您提供所需的特定数据库实例?
  • 我的项目中已经存在这样的工厂,并且被我的DataService使用。为了简单起见,我在这里省略了它。

标签: c# dependency-injection asp.net-core


【解决方案1】:

你有什么好。

除了使用 DataService 的构造函数之外,还有其他方法可以创建实例吗?也许访问 IServiceCollection 在不同位置提供的对象,而不是在只运行一次的配置阶段?也许使用我自己的 OWIN 中间件?

不是真的。您可以使用委托注册,但这是同样的问题。

这种方法真的安全吗?

是的

会不会同时发出的两个请求意外地以 DataServiceintended 为另一个请求而告终,从而最终给出错误的数据?

不。 IHttpContextAcessor 使用 AsyncLocal (http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html) 提供对“当前”http 上下文的访问。

【讨论】:

    猜你喜欢
    • 2017-09-04
    • 2021-10-04
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    相关资源
    最近更新 更多