【问题标题】:IServiceCollection override a single constructor argumentIServiceCollection 覆盖单个构造函数参数
【发布时间】:2016-11-07 13:51:52
【问题描述】:

我有一个接受三个构造函数参数的类。在我的组合根中,我只想定义/覆盖三个构造函数参数中的 一个;其他两个依赖项已经映射到我的 DI 容器中,应该从 IServiceProvider 创建。

使用 Ninject 我可以做这样的事情:

Bind<IMyInterface>().To<MyClass>()    
    .WithConstructorArgument("constructorArgumentName", x => "constructor argument value");

当 Ninject 创建 MyClass 时,它使用此字符串参数并自动为我注入其他两个依赖项。我在 .net 核心中遇到的问题是我无法告诉 IServiceCollection 我只想指定三个参数之一,我必须定义所有参数或一个都不定义。例如,在 .net 核心中,这是我必须做的:

services.AddTransient<IMyInterface>(x=> new MyClass("constructor argument value", new Dependency2(), new Dependency3());

我不喜欢创建 Dependency2 和 Dependency3 类的新实例;这两个类可以有自己的构造函数参数。我只想让 DI 管理这些依赖项。所以我的问题是 - 在使用 IServiceCollection 类映射 .net 核心中的依赖项时如何覆盖单个构造函数参数?

如果您不能仅覆盖单个构造函数参数,那么如何使用 IServiceCollection 解决依赖关系?我试着做这样的事情:

services.AddTransient<IMyInterface>(x=> new MyClass("constructor argument value", serviceCollection.Resolve<IDependency2>(), serviceCollection.Resolve(IDependency3>());

但这不起作用,我不知道如何使用 IServiceCollection 解决依赖关系。

【问题讨论】:

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


    【解决方案1】:

    试试这个:

    services.AddTransient<IDependency2, Dependency2Impl>();
    
    services.AddTransient<IDependency3, Dependency3Impl>();
    
    services.AddTransient<IMyInterface>(provider=>
        return new MyClass("constructor argument value",
          provider.GetService<IDependency2>(),
          provider.GetService<IDependency3>());
    );
    

    【讨论】:

    • 您在那里有一个“提供者”类,但我看不出它是什么或它来自哪里?我上面的代码位于具有此签名的方法中的 Startup.cs 类中:public void ConfigureServices(IServiceCollection services)。 'provider' 类在哪里创建?
    • providerFunc 参数,其类型为IServiceProvider。在您的问题中,您将其定义为“x”。
    • 哦,我明白了。我完全忽略了这一点:)。谢谢,效果很好!
    • 我正在寻找 AutoFac 的 RegisterInstance 的 .NET Core 替代方案,您可以在其中注册一个采用构造函数参数的实例,这似乎符合要求
    【解决方案2】:

    示例:
    服务缺点:

    public SkillsService(IRepositoryBase<FeatureCategory> repositoryCategory, int categoryId)
    

    启动:

     services.AddScoped<ISkillsService>(i => new SkillsService(services.BuildServiceProvider().GetService<IRepositoryBase<FeatureCategory>>(), AppSettingsFeatures.Skills));
    

    【讨论】:

      【解决方案3】:

      对于任何想要通用但灵活的解决方案的人:https://gist.github.com/ReallyLiri/c669c60db2109554d5ce47e03613a7a9

      API 是

      public static void AddSingletonWithConstructorParams<TService, TImplementation>(
                  this IServiceCollection services,
                  object paramsWithNames
              );
      public static void AddSingletonWithConstructorParams(
                  this IServiceCollection services,
                  Type serviceType,
                  Type implementationType,
                  object paramsWithNames
              );
      public static void AddSingletonWithConstructorParams<TService, TImplementation>(
                  this IServiceCollection services,
                  params object[] parameters
              );
      public static void AddSingletonWithConstructorParams(
                  this IServiceCollection services,
                  Type serviceType,
                  Type implementationType,
                  params object[] parameters
              );
      

      用构造方法反射实现。

      【讨论】:

        猜你喜欢
        • 2023-03-06
        • 2014-06-09
        • 1970-01-01
        • 2014-04-11
        • 1970-01-01
        • 2017-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多