如何将运行时参数作为泛型类的依赖关系解析的一部分传递?

时间:2019-04-11 07:46:58

标签: asp.net-core dependency-injection asp.net-core-2.0 ioc-container

这里已经回答了类似的问题:

How can I pass a runtime parameter as part of the dependency resolution?

但是,我想知道在注册通用类时如何做到这一点?

通常,我将其注册如下:

services.AddScoped(typeof(ITest<>), typeof(Test<>));

但是,如果我想将运行时参数传递给构造函数怎么办?如果不使用DI,则类似于:

new Test<MyClass>(string mystring, int myInt)

在链接的答案中,建议使用工厂方法,但这会给我一个错误,如果我没有正确传递其类型。

另一种选择是获取实例而不在构造函数中传递运行时参数,而是在获取确切实例之后使用setter方法。但是,我想避免这种情况,因为每次获取实例后,您都必须记住调用setter方法。

有没有解决的办法?我想我可以使用一些工厂类而不是在启动类中注册它...

编辑: 在阅读了非常有用的史蒂文答案之后,我用更具体的例子更新了问题: 以下示例在某些方法内:

//instance of repository are passed inside constructor of class
//calling some to update/insert
//IMPORTANT - calling external service I want save parameters to db no matter what
using(var ctx=new DbContext())
{
//create log object
ctx.logs.add(Obj)
ctx.save()
}
//some code after

假设我要保持一致并调用我的loggingrepository的方法,并在其中添加日志记录对象并将所有内容保存到数据库 但是,构造函数中的每个存储库都接受DbContext,该DbContext被注册为作用域(第一个请求)。 如果是事务内部的,则保存取决于调用外部服务后的代码,并且它可能引发异常并且不保存任何内容。

是的,我可以创建新的dbContext并将其传递到日志记录方法中,或者调用一些私有日志记录函数并保存在其中, 但是要点是,如果我要询问loggingRepository的实例,我想让DI将此本地创建的dbContext变量传递给构造函数 而不是在启动方法内部注册为作用域,因此无论调用什么外部服务或代码,都将发生addind和保存日志。

我的情况类似,但是它将基于当前用户在db中获取一些数据,我不想将相同的参数传递给众多方法,而只能传递给类构造函数。

1 个答案:

答案 0 :(得分:2)

将原始 配置值 注入到应用程序组件中的一般解决方案是将它们提取到Parameter Object中。这为这些值提供了一个新的,明确的类型,可以将其注册到您的容器中:

// Parameter Object
public TestConfiguration
{
    public string Mystring;
    public int MyInt;
}

// (Generic) class using the Parameter Object
public class Test<T>
{
    public Test(TestConfiguration config) { ... }
}

// Registering both
services.AddScoped(typeof(ITest<>), typeof(Test<>));
services.AddSingleton(new TestConfiguration { Mystring = ..., Myint = ... });

配置值不被认为是运行时数据,因为它们的值在启动时是已知的,并且在应用程序的持续时间内是恒定的。因此,您可以将它们提供给应用程序组件的构造函数。

但是,实际运行时数据不应在构造期间传递给组件。运行时数据是启动时 未知的值,通常是用户通过Web请求传递的值,它们是从数据库,会话或在应用程序生存期内可以更改的任何内容中检索的。 / p>

代替通过构造函数传递运行时数据,您应该:

  1. 通过API的方法调用传递运行时数据或

  2. 从允许解析运行时数据的特定抽象中检索运行时数据。

您可以找到有关传递运行时数据here的更多信息。