然后有两个请求到达controller action。
观察请求内和请求间的OperationId哪个变化。
请求服务和应用服务HttpContext中的一个ASP.NET请求中的可用服务分为两个集合,ApplicationServices和RequestServices。
Request services作为应用的一部分是你可以配置和request的。而Application Services则是局限于在在应用启动(Startup)时可用的服务。Scoped的服务是作为Request Services的一部分而不是Applocation Services的一部分。当对象指定依赖时,是由RequestServices中的类型所提供,而不是ApplicationServices。
一般来将你不应该直接使用这些属性,而是倾向于通过类的构造器来请求这些类型,让框架来注入这些依赖。这样产生的类更容易测试和更松耦合。
Note: 需要重点记住的是,应用几乎总是会使用RequestServices,任何情况下你都不应该直接使用这些属性。而是通过构造器来请求所需服务。
自定义依赖注入服务你可以设计自己的服务并通过依赖注入到需求方。这样可以避免使用有状态的静态方法调用(会导致code smell,即static cling)和服务内对依赖类的直接实例化。当选择是否通过New来实例化一个类型或者通过依赖注入来氢气,记住“New is Glue”也许是点帮助的。通过遵循Solid面向对象设计原则,设计的类自然就会small, well-factored,和easily tested。
如果你发现类有了太多需要注入的依赖怎么办?一般来说,这是类承担了太多职责的标志,很有可能违反了SRP(单一职责原则)。检查是否能把其中的某些职责转到新的类。记住,Controller类应该只关注UI,所以业务规则和数据获取实现应该放在合适的关注点分离的类中。
至于数据获取,你可以注入EF DbContext类型到Controller中(假设你已经在Startup类中配置了EF)。然而,一般避免在UI项目中直接依赖DbContext类型,而是依赖抽象,如Repository接口,在接口的实现中限制EF的相关知识。这样会减少项目和数据访问策略的耦合,使得测试代码更加容易。
取代默认服务容器内建的服务容器只满足框架最基本的需求,大部分的consumer 应用基于此构建。然而,如果开发者希望取代内建的容器,使用自己偏好的容器,也是可以很容易做到的。ConfigureServices方法一般返回void,但是如果返回类型签名改为IServiceProvider,就可以配置和返回别的容器。有很多IoC .NET容器。当它们可用时,本文会添加这些容器的DNX实现。在本例中,使用Autofac包。
首先在project.json中添加合适的容器包。
然后在ConfigureServices中配置容器,并返回IServiceProvider:
public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc(); // add other framework services // Add Autofac var containerBuilder = new ContainerBuilder(); containerBuilder.RegisterModule<DefaultModule>(); containerBuilder.Populate(services); var container = containerBuilder.Build(); return container.Resolve<IServiceProvider>(); }Note: 当使用第三方DI容器时,需要改变ConfigreServices的返回签名,改成IServiceProvider而不是void。
最后在DefaultModule中配置Autofac。
public class DefaultModule : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<CharacterRepository>().As<ICharacterRepository>(); } }然后在运行时,Autofac将会解析类型和注入的依赖
Package(Nuget)
ProjectSite
Autofac.Dnx
StructureMap.Dnx
推荐规范
当使用依赖注入时,记住如下推荐规范:
Note: 如上所有推荐规范,你可能遇到必须忽略某条的情形。但是这种情形很少,而且基本都是框架本身内部的情形。
记住,依赖注入是static/global对象获取模式的一个替代方式。如果你把DI和静态对象接入混用,你可能不能体会到DI的优势。
Download sample from GitHub