Autofac全面解析系列(版本:3.5)–[依赖注入]
前言autofacAutofac是一套高效的依赖注入框架。 依赖注入依赖注入,这个专业词我们可以分为两个部分来理解: 依赖,也就是UML中描述事物之间关系的依赖关系,依赖关系描述了事物A在某些情况下会使用到事物B,事物B的变化会影响到事物A; 注入,医生通过针头将药物注入到病人体内。注入也就是由外向内注入、灌输一些东西。 综合上面的说明,依赖注入就是A类依赖B类,B类的实例由外部向A注入,而不是由A自己进行实例化或初始化。 三种注入方式构造器注入我们先理解构造器注入的字面意思,构造器注入也就表示,依赖关系通过构造器进行注入。 这种我们平时是非常常见的,类A依赖于类B,类A的构造方法中,有一个参数为类B,在new 类A,会从外部为类B传入实例,这就是构造注入: class Program {
static void Main(string[] args)
{
var b = new B();
var a = new A(b);
}
}
class A {
private B _b;
public A(B b)
{
this._b = b;
}
}
class B { }
上面说明了构造注入的含义以及构造注入的表现形式,下面我们来看看autofac中的构造注入。 在使用autofac时,构造注入是默认行为。 以上面的代码为例,如果类型A和类型B都注册到了autofac中,那么在通过autofac解析获取A时,autofac会检测到A的构造方法中是要一个参数B,而类型B是已经注册到autofac中的,所以autofac会自动创建b参数,然后传入A的构造方法中的。这样,autofac就自动帮我们完成了构造注入的工作。 class Program {
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<A>();
builder.RegisterType<B>();
var container = builder.Build();
var a = container.Resolve<A>(); //A的构造方法需要参数b,但是这里不需要做更多地操作
}
}
属性注入属性注入也就是通过属性进行注入,我们修改上面的A类,将变量_b通过属性暴露出来,并且删掉有参构造方法,然后让我们看看我们平常写代码时怎么实现属性注入的: class Program {
static void Main(string[] args)
{
var a = new A(); //点击A查看A类修改后结构
var b = new B();
a.B = b; //通过属性来注入具有依赖关系的B
}
}
这种代码在日常中我们写过了无数遍,即使是这么平常的代码,但这就是属性注入。
说完注意点,让我们再来看看autofac是怎么进行属性注入的: 自动属性注入属性注入的所有注入方式都是在注册时定义的,不像构造注入那般,可以在 构造器注入是默认行为,不需要设置,默认会去检查,而属性注入并不是默认行为。但是我们可以通过设置,让属性注入也成为自动注入。 class Program {
static void Main(string[] args)
{
var builder = new ContainerBuilder();
// 通过PropertiesAutowired制定类型A在获取时会自动注入A的属性
builder.RegisterType<A>().PropertiesAutowired();
builder.RegisterType<B>();
var container = builder.Build();
var a = container.Resolve<A>();
Console.Write("Press any key to continue...");
Console.ReadKey();
}
}
使用 WithProperty、WithProperties
class Program {
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<A>().WithProperty(new NamedPropertyParameter("B",new B()));
// builder.RegisterType<A>().WithProperty("B",new B()); //效果与上面相同
var container = builder.Build();
var a = container.Resolve<A>();
Console.Write("Press any key to continue...");
Console.ReadKey();
}
}
用法简单, lambda在注册篇里面有讲到一种lambda注册方式,lambda注册时,因为是写lambda表达式进行注册,其lambda内容可以写很多,其中就可以进行属性注入: var builder = new ContainerBuilder();
builder.Register(c =>
{
var _a = new A();
_a.B = new B(); //手动注入
return _a;
});
这里的注入,就是最开始讲到属性注入时的那种赋值注入。 事件在autofac中,还有一些事件,这些事件在不同时期触发,事件相关的具体内容将在后续说明。在注入中能够使用到的事件有 var builder = new ContainerBuilder();
builder.RegisterType<A>().OnActivating(e =>
{
e.Instance.B = new B(); //Instance为Resolve出来的实例,类型为A
});
方法注入方法注入也不是默认行为,而且还没有提供像属性注入那样的自动注入设置。 方法注入有两种方式,也就是属性注入的后两种方式:lambda以及事件。大家应该已经能够想到注入的代码是什么样了: var builder = new ContainerBuilder();
// lambda
builder.Register(cc =>
{
var _a = new A();
_a.MethodInjection(new B());
return _a;
});
// 事件
builder.RegisterType<A>().OnActivated(e =>
{
e.Instance.MethodInjection(new B());
});
class A
{
public void MethodInjection(B b)
{
// 做一些操作
}
}
这段代码可能与一些朋友想象中的不一样,有些朋友可能想着A中还有一个成员_b,然后在方法 不是两个类型之间一定是成员关系,然后才能有依赖注入,我们得理解依赖的含义。A类型在某些操作中需要使用到B类型,而并不将B类型持久的保存起来,临时使用也是一种依赖关系。关于为什么这样就算作依赖注入,在我们了解刚刚说的依赖关系后,再来看看依赖的注入与不注入的不同形式,如果不是注入的方式,那么B类型将不做为参数传入,而直接在方法中new。 而依赖注入的好处,在这里还不能很好的看到,因为现在是在讲autofac中关于注入的方式。如果想更只管的看到注入的好处,我们将参数B换成接口 尾述疑问关于注入这块儿,其实我个人有个疑问,关于autofac。属性注入中,我们可以通过设置 而我想的这种 尾述个人还是推荐使用默认最简单的构造注入,不需要传参的那种;属性注入推荐设置自动属性注入,如果能够找到疑问中说到的那种 其实这里的推荐原则是这样的,需要在注册时进行指定注入的方式实际是不太好的,因为后来的人可能不太清楚每个类型的注入规则,还需要到注册的地方进行查看,而且不同人员写的不同,这样容易混乱。而在获取时进行注入,实际也是不太妥的,因为在实际的用法中,我们会将注册类型与接口进行关联,在获取时直接获取接口类型。也正因为我们获取时获取的是接口类型,我们无法保证接口的实际实现是不是具有我们预期的参数。 如果有任何问题,还希望大家能够提出讨论,互相学习。也希望能够有前辈对博客的内容及表达方式提出意见和建议,谢谢! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |