C# DI实际上是如何对属性进行注入的?
我绞尽脑汁找不到合适的答案,所以我们开始吧!我的每种形式或对象都具有以下属性:C# DI实际上是如何对属性进行注入的?,c#,dependency-injection,C#,Dependency Injection,我绞尽脑汁找不到合适的答案,所以我们开始吧!我的每种形式或对象都具有以下属性: private RootWorkItem m_RootWorkItem; [RootWorkItem(Inject = true)] public RootWorkItem RootWorkItem { get { if (m_RootWorkItem == null) { m_RootWorkItem = new Ro
private RootWorkItem m_RootWorkItem;
[RootWorkItem(Inject = true)]
public RootWorkItem RootWorkItem {
get {
if (m_RootWorkItem == null) {
m_RootWorkItem = new RootWorkItem();
}
return m_RootWorkItem;
}
}
注意,RootWorkItem是我设计的一个类,它包含一个服务集合(collection)。基本上,我的所有服务都是使用反射和Activator.CreateInstance从外部DLL文件加载的,并放入RootWorkItem.services中
但我究竟如何才能将创建的第一个RootWorkItem“注入”到程序中标记有我的属性的其他RootWorkItem中呢
这些DI模式实际上是如何“注入”到“属性”中的?我知道DI的概念,但我正试图为一个对象编写我自己的、非常基本的DI。我一直在尝试寻找一些合适的方法来做这件事,我甚至还没有找到一个正确的方法来做这件事
编辑以获得更清晰的问题:
DI框架/服务如何知道何时创建了包含要注入的属性的对象
即:
如果没有任何东西通知服务它已创建或需要注入属性值,那么它如何知道在创建表单时注入属性值?通常,依赖注入框架使用属性和反射来发现哪些字段、属性,类的方法要求在创建时注入依赖项,然后使用反射来实际注入依赖项,从而绕过正常的访问器限制,例如,注入到私有字段中 我觉得你的例子不对。属性位于只读属性上,该属性不能通过反射或任何其他方式设置。我希望您的示例如下所示:
[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {
get {
if (m_RootWorkItem == null) {
m_RootWorkItem = new RootWorkItem();
}
return m_RootWorkItem;
}
}
[Inject(true)]
public RootWorkItem RootWorkItem { get; private set; }
您的混淆是否可能源于属性的放置
此外,由于您正在将m_RootWorkItem
的值注入到字段中,因此不再需要保护您的属性
[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {
get {
return m_RootWorkItem;
}
}
因此,您可以进一步使用自动实现的属性:
[RootWorkItem(Inject = true)]
public RootWorkItem RootWorkItem { get; private set; }
最后,我不确定为什么属性类型与属性类型和名称相同。然后我会期待更像这样的事情:
[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {
get {
if (m_RootWorkItem == null) {
m_RootWorkItem = new RootWorkItem();
}
return m_RootWorkItem;
}
}
[Inject(true)]
public RootWorkItem RootWorkItem { get; private set; }
我不知道您使用的是什么框架,因此无法对true
参数的作用进行评论,因此我将其逐字包含在内
由于正在编辑的问题而被编辑
您缺少了依赖项注入框架也是一个抽象工厂的概念
因此,您不会直接创建MyForm
实例。相反,您可以通过某种方式向DI容器注册MyForm
类型,然后使用该容器为您创建实例。然后,它将创建实例,但在将实例返回给您之前,它将注入依赖项(通过对属性的反射发现)
例如:
// configure at start-up
container.Register<MyForm>();
// some point later in your code
MyForm mf = container.Resolve<MyForm>();
//启动时配置
container.Register();
//代码后面的某个点
MyForm mf=container.Resolve();
通常,依赖项注入框架使用属性和反射来发现类的哪些字段、属性和方法需要在创建时注入依赖项,然后使用反射来实际注入依赖项-从而绕过正常的访问器限制-注入到私有字段,比如说
我觉得你的例子不对。属性位于只读属性上,该属性不能通过反射或任何其他方式设置。我希望您的示例如下所示:
[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {
get {
if (m_RootWorkItem == null) {
m_RootWorkItem = new RootWorkItem();
}
return m_RootWorkItem;
}
}
[Inject(true)]
public RootWorkItem RootWorkItem { get; private set; }
您的混淆是否可能源于属性的放置
此外,由于您正在将m_RootWorkItem
的值注入到字段中,因此不再需要保护您的属性
[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {
get {
return m_RootWorkItem;
}
}
因此,您可以进一步使用自动实现的属性:
[RootWorkItem(Inject = true)]
public RootWorkItem RootWorkItem { get; private set; }
最后,我不确定为什么属性类型与属性类型和名称相同。然后我会期待更像这样的事情:
[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {
get {
if (m_RootWorkItem == null) {
m_RootWorkItem = new RootWorkItem();
}
return m_RootWorkItem;
}
}
[Inject(true)]
public RootWorkItem RootWorkItem { get; private set; }
我不知道您使用的是什么框架,因此无法对true
参数的作用进行评论,因此我将其逐字包含在内
由于正在编辑的问题而被编辑
您缺少了依赖项注入框架也是一个抽象工厂的概念
因此,您不会直接创建MyForm
实例。相反,您可以通过某种方式向DI容器注册MyForm
类型,然后使用该容器为您创建实例。然后,它将创建实例,但在将实例返回给您之前,它将注入依赖项(通过对属性的反射发现)
例如:
// configure at start-up
container.Register<MyForm>();
// some point later in your code
MyForm mf = container.Resolve<MyForm>();
//启动时配置
container.Register();
//代码后面的某个点
MyForm mf=container.Resolve();
您提出了正确的问题:“如果没有任何内容通知服务它已创建或需要注入,那么它如何知道在创建表单时注入属性值?”
如果您说“如果没有任何东西通知服务它是创建的或需要注入的”,那么DI框架就不能完成它的工作,这也是正确的
但是,DI框架确实知道,因为您使用DI框架来创建注入依赖项的对象。在本例中,您使用DI框架来创建表单,因此它可以感知对象并可以注入依赖项
而不是
MyForm form = new MyForm();
form.Show();
做
现在,您的DI框架了解了对象
本质上,
new
是DI的敌人,因为它意味着调用者正在控制对象的构造。取而代之的是,调用者将责任留给其他人,即DI框架。调用者应该只要求DI框架提供/构造/配置对象。你问的问题是正确的:“它是如何知道