【问题标题】:How to use dependency injectionen and argument in the same time?如何同时使用依赖注入和参数?
【发布时间】:2019-12-06 12:02:47
【问题描述】:

我有课

public TimeSeriesBusinessComponent(IContextRepository contextRepository)  { ...

我通过我的类 ServiceExtension 传递依赖项注入,我从 Startup.cs 调用它。

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
   services.AddRepositories(Configurations);
   services.AddBusinessComponents();

服务扩展:

public static void AddRepositories(this IServiceCollection serviceCollection, Configurations con)
{
   serviceCollection.AddScoped<IContextRepository>(serviceProvider =>
   {
       string createContextFunctionName = con.Get(CREATE_CONTEXT_FUNCTION_NAME);
       return new ContextRepository(createContextFunctionName);
   });
}

public static void AddBusinessComponents(this IServiceCollection serviceCollection)
{
    serviceCollection.AddScoped<ITimeSeriesBusinessComponent, TimeSeriesBusinessComponent>();
}

后来我像这样使用我的类 TimeSeriesBusinessComponent:

public class TimeSeriesController : Controller
{
    private ITimeSeriesBusinessComponent BusinessComponent { get; }

    public TimeSeriesController(
        ITimeSeriesBusinessComponent businessComponent
        )
    {
        BusinessComponent = businessComponent;
    }

但现在我也需要将一个参数从我的 ServicExtension 转移到我的 TimeSeriesBusinessComponent 中,例如 ..

public TimeSeriesBusinessComponent(IContextRepository contextRepository,. string value)  { ...

我从配置中获得的字符串值 (EnvirenmentVariables)。

如何同时使用依赖注入和普通参数?

【问题讨论】:

  • string value 参数从何而来?从某种配置或?目前尚不清楚:谁创建了您的 TimeSeriesBusinessComponent 类的实例:DI 还是您?
  • @deezg 我在最初的帖子中添加了信息。
  • 如果字符串值是在运行时生成的,您可以简单地引入Init 函数或类似的函数,您可以在其中传递这样的字符串。您可以(或者甚至不应该)混合 DI 和手动实例化。在 autofac 例如可以将 container.Resolve 与 ConstructorParameters 参数一起使用,但即使这种方法也不适用于松散的使用场景

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


【解决方案1】:

因此,由于您的字符串值来自环境变量,您应该使用IOptions

  1. 您创建您的 MyOptions 类(它将保存您需要的值)
  2. 您在Startup.cs 中从您的环境(或任何地方)加载一个值
  3. 您使用 DI 容器注册您的选项
  4. 您将其注入目标类,就像任何其他服务一样

例如:

services.Configure<MyOptions>(options =>
  {
    options.MyString = Environment.GetEnvironmentVariable("MY_STRING_KEY");
  });

然后你像这样使用它:

public TimeSeriesBusinessComponent(IContextRepository contextRepository, IOptions<MyOptions> myOptions) {

_myOptionsOptions = options.MyString;

}

文档:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.2

【讨论】:

  • 你不需要注入 IOptions&lt;MyOptions&gt; 本身。您也可以将MyOptions 直接注入TimeSeriesBusinessComponent 的构造函数中。这里的实际技巧是将配置值包装在参数对象中,因为这样可以防止在注入值时产生歧义:string 是一种歧义类型。
  • @Steven 当然,但IOptions&lt;T&gt; 是一个很好的起点,如果你想继续进行更高级的场景(如通知等),如 docs ref 所示。但你是对的,options 对象本身可以被注入。
  • 我添加了一个具有公共 int NumberOfTimeSeries 属性的类 ConfigurationValues。在启动时我写: services.Configure(options => {options.NumberOfTimeSeries = 100;});在我的 TimeSeriesBusinessClass 构造函数中,我添加了 IOptions myOptions。但对象 myOptions 上没有 NumberOfTimeSeries 属性。我做错了什么?
  • var v = myOptions.Value.NumberOfTimeSeries;所以它有效! :-) 谢谢 ! ! !
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-18
  • 2010-12-07
  • 2022-12-18
  • 2014-01-01
  • 1970-01-01
  • 2023-03-09
相关资源
最近更新 更多