Autofac中文文档--二、解析服务--2隐式关系类型
来源:互联网 发布:sketch mac 激活码 编辑:程序博客网 时间:2024/05/16 05:50
Autofac 隐式关系类型
1、支持的关系类型
Parameterized Instantiation(参数化实例化)
A needs all the kinds of BIEnumerable<B>, IList<B>,
ICollection<B>
Enumeration(枚举)A needs to know X about BMeta<B> and Meta<B,X>Metadata InterrogationA needs to choose B based on XIIndex<X,B>Keyed Service Lookup(键控服务查找)1.1Direct Dependency (B)--直接依赖
public class A{ public A(B dependency) { ... }}
var builder = new ContainerBuilder();builder.RegisterType<A>();builder.RegisterType<B>();var container = builder.Build();using(var scope = container.BeginLifetimeScope()){ // B 自动注入到 A 中 var a = scope.Resolve<A>();}
1.2Delayed Instantiation (Lazy<B>)--惰性依赖
public class A{ Lazy<B> _b; public A(Lazy<B> b) { _b = b } public void M() { // 在第一次调用 M() 方法时,创建组件 B _b.Value.DoSomething(); }}
1.3 Controlled Lifetime (Owned<B>)
public class A{ Owned<B> _b; public A(Owned<B> b) { _b = b; } public void M() { // _b is used for some task _b.Value.DoSomething(); // 这里 _b 不再需要,所以,释放他 _b.Dispose(); }}
在内部,Autofac创建一个微小的lifetime scope,其中对B服务解析,且当你调用它的Dispose()时,这个lifetime scope 将被处理。这也就意味着,释放B也将释放它的依赖关系,除非这些依赖是共享的。
var builder = new ContainerBuilder();builder.RegisterType<A>().InstancePerLifetimeScope();builder.RegisterType<B>().InstancePerLifetimeScope();var container = builder.Build();using(var scope = container.BeginLifetimeScope()){ // 这里解析一个使用了 InstancePerLifetimeScope() 的 类型 B ; var b1 = scope.Resolve<B>(); b1.DoSomething(); // 这个和上面的 b1 一样。 var b2 = scope.Resolve<B>(); b2.DoSomething(); // 在类型 A 中使用的类型 B 和其他地方的 B 不是同一个 var a = scope.Resolve<A>(); a.M();}
设计就是这样的,因为你不想让一个组件处理 B 下的一切事情。然而,如果你不知道,它可能会导致一些混乱。
1.4 Dynamic Instantiation (Func<B>)--动态实例化
public class A{ Func<B> _b; public A(Func<B> b) { _b = b; } public void M() { var b = _b(); b.DoSomething(); }}
1.5Parameterized Instantiation (Func<X, Y, B>)
public class A{ Func<int, string, B> _b; public A(Func<int, string, B> b) { _b = b } public void M() { var b = _b(42, "http://hel.owr.ld"); b.DoSomething(); }}
在内部,Autofac将它们视为类型的参数。这也就意味着,自动生成函数工厂,不能在输入参数列表中有重复的类型。例如,你有这样一个类型:
public class DuplicateTypes{ public DuplicateTypes(int a, int b, string c) { // ... }}
var func = scope.Resolve<Func<int, int, string, DuplicateTypes>>();// Throws a DependencyResolutionException:var obj = func(1, 2, "three");
在一个松耦合的场景下,其中的参数需与类型相匹配,你不了解特定对象的构造函数的参数顺序。如果你需要做这样的事情,你应该使用自定义的委托类型来代替:
public delegate DuplicateTypes FactoryDelegate(int a, int b, string c);
RegisterGeneratedFactory()注册委托
:builder.RegisterType<DuplicateTypes>();builder.RegisterGeneratedFactory<FactoryDelegate>(new TypedService(typeof(DuplicateTypes)));
现在这个函数将工作:
var func = scope.Resolve<FactoryDelegate>();var obj = func(1, 2, "three");
你有另一种方式,就是使用使用委托工厂。
var func = container.Resolve<Func<int, string, DuplicateTypes>>();// This works and is the same as calling// new DuplicateTypes(1, 1, "three")var obj = func(1, "three");
使用这种关系类型且使用委托工厂时推荐使用Lifetime scopes.如果您注册一个对象为InstancePerDependency(),并多次调用Func<X,Y,B>
,每次你将得到一个新实例。但是,如果你注册一个对象为SingleInstance(),并调用Func<X,Y,B>
多次解析对象,你每次都会得到同一个对象实例即使你传递不同的参数。仅仅传递不同的参数不能打破lifetime scope。
1.6 Enumeration (IEnumerable<B>, IList<B>, ICollection<B>)
public interface IMessageHandler{ void HandleMessage(Message m);}
此外,你有一个用户的依赖关系,你需要有多个注册和用户需要的所有注册的依赖关系:
public class MessageProcessor{ private IEnumerable<IMessageHandler> _handlers; public MessageProcessor(IEnumerable<IMessageHandler> handlers) { this._handlers = handlers; } public void ProcessMessage(Message m) { foreach(var handler in this._handlers) { handler.HandleMessage(m); } }}
您可以使用隐枚举关系类型很容易地做到这一点。只需注册所有的依赖和用户,并且当你解析用户,它所匹配的所有依赖将被解析为一个枚举:
var builder = new ContainerBuilder();builder.RegisterType<FirstHandler>().As<IMessageHandler>();builder.RegisterType<SecondHandler>().As<IMessageHandler>();builder.RegisterType<ThirdHandler>().As<IMessageHandler>();builder.RegisterType<MessageProcessor>();var container = builder.Build();using(var scope = container.BeginLifetimeScope()){ // When processor is resolved, it'll have all of the // registered handlers passed in to the constructor. var processor = scope.Resolve<MessageProcessor>(); processor.ProcessMessage(m);}
如果没有匹配的项目在容器中注册,枚举将返回一个空集。也就是说,使用上面的例子,如果你没有注册任何IMessageHandler 实现时,它将中断:
// This throws an exception - none are registered!scope.Resolve<IMessageHandler>();
// This returns an empty list, NOT an exception:scope.Resolve<IEnumerable<IMessageHandler>>();
你可能认为,如果你使用这种关系注入东西,你会得到一个空值。相反,你会得到一个空列表。
1.7Metadata Interrogation (Meta<B>, Meta<B, X>)
public class A{ Meta<B> _b; public A(Meta<B> b) { _b = b; } public void M() { if (_b.Metadata["SomeValue"] == "yes") { _b.Value.DoSomething(); } }}
你也可以使用 strongly-typed 元数据, 通过在 Meta<B,X>
关系中指定元数据类型:
public class A{ Meta<B, BMetadata> _b; public A(Meta<B, BMetadata> b) { _b = b; } public void M() { if (_b.Metadata.SomeValue == "yes") { _b.Value.DoSomething(); } }}
如果你有一个惰性依赖也需要元数据,你可以使用Lazy<B,M> 代替Meta<Lazy<B>, M>
1.8 Keyed Service Lookup (IIndex<X, B>)
var builder = new ContainerBuilder();builder.RegisterType<DerivedB>().Keyed<B>("first");builder.RegisterType<AnotherDerivedB>().Keyed<B>("second");builder.RegisterType<A>();var container = builder.Build();
然后使用IIndex<X,B>得到一个keyd服务字典:
public class A{ IIndex<string, B> _b; public A(IIndex<string, B> b) { _b = b; } public void M() { var b = this._b["first"]; b.DoSomething(); }}
2、组成关系类型
IEnumerable<Func<Owned<ITask>>>
正确的解释为:
- All implementations, of
- Factories, that return
- Lifetime-controlled
- ITask services
3、关系类型和容器独立
Func<Owned<ITask>>
的AutofacTaskFactory实现。- Autofac中文文档--二、解析服务--2隐式关系类型
- Autofac官方文档(九)【解析服务之隐式关系类型】
- Autofac中文文档--二、解析服务--1解析参数传递
- Autofac官方文档(七)【解析服务】
- Autofac官方文档(二)【新版本】
- Autofac中文文档--一、注册组件--2传递注册参数
- AutoFac文档2
- Autofac官方文档(八)【解析服务之传递参数来解析】
- [Autofac]服务类型、 名称和键
- Autofac官方文档(二十)【应用集成】
- Autofac中文文档--一、注册组件--1注册概念
- Autofac中文文档--一、注册组件--4组件扫描
- Autofac官方文档(二十一)【应用集成之OWIN】
- Autofac官方文档(二十二)【应用集成之MVC】
- Autofac官方文档(二十三)【应用集成之Web API】
- Autofac官方文档(二十四)【应用集成之Web Forms】
- Autofac中文文档--一、注册组件--3属性和方法注入
- Autofac官方文档(一)【开始】
- android屏幕录制adb及转换gif实现
- iOS CoreTelephony框架介绍与使用案列
- java学习阶段建议(转自他人微博)
- 1005. Spell It Right (20)
- 算法题 之 lucky_price
- Autofac中文文档--二、解析服务--2隐式关系类型
- Linux下得到主机的信息(生产商,型号,主机序列号)
- RasValidateEntryName
- ARM C、汇编混合编程
- Java设计模式—备忘录模式
- 【宽搜】ECNA 2015 D Rings (Codeforces GYM 100825)
- hdu1757 - A Simple Math Problem
- Spring aop--几种不同的使用方式
- WEBRTC音视频接收(从网络接收RTP包到组帧)