这里已经回答了类似的问题:
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中获取一些数据,我不想将相同的参数传递给众多方法,而只能传递给类构造函数。
答案 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>
代替通过构造函数传递运行时数据,您应该:
通过API的方法调用传递运行时数据或
从允许解析运行时数据的特定抽象中检索运行时数据。
您可以找到有关传递运行时数据here的更多信息。