使用 DI 注入一些参数,并手动分配一些参数
Posted
技术标签:
【中文标题】使用 DI 注入一些参数,并手动分配一些参数【英文标题】:Having some parameters Injected with DI and some assigned manually 【发布时间】:2021-11-28 11:15:03 【问题描述】:在 .NET Core 3.1 控制台应用程序中,我想要一个在构造函数中注入一些参数但我可以手动分配的类。例如类似的东西,但注入了 IConfiguration:
static void Main()
var myObj1 = new MyClass(1);
var myObj2 = new MyClass(2);
public class MyClass
public MyClass(IConfiguraiton config, int myVal)
我用 Ninject 试过这个:
static void Main()
kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Get<MyClass>();
public class MyClass
public MyClass(IConfiguraiton config)
public class Bindings : NinjectModule
public override void Load()
var configuration = new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build();
Bind<IConfiguration>().ToMethod(ctx => SetupConfiguration()).InSingletonScope();
Bind<MyClass>().ToSelf().InTransientScope();
我设法进行了简单的依赖注入,但没有成功使用参数进行注入。
我读过很多人建议最好将参数传递给类的方法而不是构造函数,但是在我的情况下,这不是一个选择,另外我是一名软件工程专业的学生,并且希望了解如何执行此操作,因为它在某些情况下可能很有用。
【问题讨论】:
如果你想自己创建依赖注入有什么意义?将这些值封装到注入到类中的另一个配置提供程序等中。 是的,这个有点不适合。你可以做些什么来解决它是使用属性注入(NInject 支持它),然后像var my = new MyClass myProp = 1 ;
那样在初始值中提供你的其他属性。然而,属性注入通常是不受欢迎的,因为开发人员不清楚哪些东西被注入了,哪些东西没有被注入,并且在测试代码时很容易错过一些
另外 - however in my situation this isn't an option in addition
- 为什么不呢?
注入值的作用是什么?这个值是恒定的,在应用程序运行时不改变,并且在启动时可用,或者更确切地说是一个可能在每个请求上改变的运行时值。或者可能介于两者之间。请描述其功能和起源;正确的解决方案在很大程度上取决于您给出的答案。
好的,很抱歉关于上下文的信息太少了。所以 MyClass 将是一个负责下载网站文件的类。因此,我想要传递的值将是指向该网站的链接。我不想将值传递给方法,因为在这个类中会有很多方法使用链接,所以使用构造函数会更有意义吗?我不能在配置中拥有该值,因为我将创建该类的多个实例来从不同的网站下载文件。
【参考方案1】:
这是Ninject.Extensions.Factory 很有用的情况,因为它正是为这种情况而设计的。除了 Castle.Core, as it uses DynamicProxy 之外,它还引入了 Factory 依赖项(作为 SE 学生,使用此库是使用 interceptor pattern 的好主意)。
要使用它,您可以像这样定义一个工厂接口:
public interface IMyClassFactory
MyClass Create(int myVal);
注意Create
方法返回MyClass
,Create
方法的参数在类型和名称上与您希望提供的参数完全匹配。您要注入的参数类型必须在内核中注册。不幸的是,这里很容易出错——如果你指定了一个在工厂接口中不存在的参数,它会被忽略,但如果你忘记了一个参数,它会在调用时抛出异常。
接下来,像这样注册IMyClassFactory
:Bind<IMyClassFactory>().ToFactory();
并删除您对MyClass
的绑定。然后在需要创建实例的任何地方注入IMyClassFactory
并调用Create
:kernel.Get<IMyClassFactory>().Create(2)
您可以在不使用Ninject.Extensions.Factory 的情况下通过编写和注册您自己的IMyClassFactory
实现来获得相同的结果,基本上与Factory 扩展最终发出的代码相同。下面是一个完整的示例,使用基于注释输入/输出注册的两种方法(如果将 .InSingletonScope()
添加到 IConfiguraiton
的注册中,请注意输出 - 两种方法都尊重 Ninject 的绑定范围)。
internal class Program
static void Main(string[] args)
var kernel = new StandardKernel();
kernel.Bind<IConfiguraiton>().To<Configuraiton>();
kernel.Bind<IMyClassFactory>().ToFactory();
//kernel.Bind<IMyClassFactory>().To<NinjectMyClassFactory>().InSingletonScope();
var factory = kernel.Get<IMyClassFactory>();
var one = factory.Create(1);
var two = factory.Create(2);
public interface IMyClassFactory
MyClass Create(int myVal);
public class NinjectMyClassFactory : IMyClassFactory
public NinjectMyClassFactory(IResolutionRoot resolutionRoot)
ResolutionRoot = resolutionRoot;
private IResolutionRoot ResolutionRoot get;
public MyClass Create(int myVal)
return ResolutionRoot.Get<MyClass>(new ConstructorArgument("myVal", myVal));
public class MyClass
public MyClass(IConfiguraiton config, int myVal)
Console.Out.WriteLine("Created MyClass(0,1)", config.MyNum, myVal);
public interface IConfiguraiton int MyNum get;
public class Configuraiton : IConfiguraiton
static int CreateCount;
public Configuraiton()
MyNum = Interlocked.Increment(ref CreateCount);
public int MyNum get;
【讨论】:
以上是关于使用 DI 注入一些参数,并手动分配一些参数的主要内容,如果未能解决你的问题,请参考以下文章