ASP.NET Core 依赖注入基本用法
原文:
ASP.NET Core 依赖注入基本用法
ASP.NET Core 依赖注入ASP.NET Core从框架层对依赖注入提供支持。也就是说,如果你不了解依赖注入,将很难适应 ASP.NET Core的开发模式。本文将介绍依赖注入的基本概念,并结合代码演示如何在 ASP.NET Core中使用依赖注入。 什么是依赖注入?百度百科对于依赖注入的介绍:
从百科的介绍中可以看出,依赖注入和控制反转是一回事,依赖注入是一种新的设计模式,通过正确使用依赖注入的相关技术,可以降低系统耦合度,增加系统的可扩展性。 我们来看一个例子: public interface IInterfaceA { } public interface IInterfaceB { } public class ClassA : IInterfaceA { private IInterfaceB B { get; set; } public ClassA(IInterfaceB b) { this.B = b; } } public class ClassB : IInterfaceB { } 这个时候,如果我们想要获取IInterfaceA的实例,如果不采用依赖注入,我们的做法通常是这样的: IInterfaceB b = new ClassB(); IInterfaceA a = new ClassA(b); 这个时候IInterfaceA的控制权,在实例化的时候就已经被限定死了,没有任何想象空间,就是ClassA的实例,并且我们还要手工的初始化IInterfaceB,同样B的控制权也被限定死了。这样的代码毫无设计、也极不利于扩展。 如果采用依赖注入,我们看一下代码: var a = container.GetService<IInterfaceA>(); 这个时候接口A和B的控制权是由容器来控制的,我们可以通过向容器中注入不同的接口实现来扩展系统的灵活性,由于将控制权交给了IoC容器,我们还可以通过配置的方式灵活的控制对象的生命周期,这一点也是手工创建对象无法实现的。 控制反转的关系图如下(图片来源于官网): ASP.NET Core中的依赖注入上面介绍了依赖注入的基本概念,那么在 ASP.NET Core中,我们该如何使用依赖注入呢?在 ASP.NET Core中已经内置了一套依赖注入的容器,我们可以直接使用。 在Startup.ConfigureServices中添加我们要注册的服务和实现,添加的时候可以对服务的生命周期进行相应的配置,然后就可以在PageModel、Controller、Views等需要的地方使用了。 下面的示例将演示如何注册服务,代码来源于官网。首先要定义一个服务接口,并实现这个接口: public interface IMyDependency { Task WriteMessage(string message); } public class MyDependency : IMyDependency { private readonly ILogger<MyDependency> _logger; public MyDependency(ILogger<MyDependency> logger) { _logger = logger; } public Task WriteMessage(string message) { _logger.LogInformation( "MyDependency.WriteMessage called. Message: {MESSAGE}",message); return Task.FromResult(0); } } 然后我们进行服务注册: public void ConfigureServices(IServiceCollection services) { services.AddScoped<IMyDependency,MyDependency>(); services.AddMvc(); } 这里我们添加了IMyDependency的注册,同时也添加了使用Mvc所需要的服务的注册。这里有两个问题需要说明:
namespace Microsoft.Extensions.DependencyInjection { public static partial class MyDependencyExtensions { public static IServiceCollection AddMyDependency(this IServiceCollection services) { return services.AddScoped<IMyDependency,MyDependency>(); } } } 使用依赖注入在了解了依赖注入的基本用法之后,我们现在来了解一下如何将服务注入到Controller、Views中。 在控制器中注入服务最常规的用法是采用构造函数注入的方式,将一个服务注入到控制器中,代码如下: public class DefaultController : Controller { private readonly ILogger<DefaultController> logger; public DefaultController(ILogger<DefaultController> logger) { this.logger = logger; } } 构造函数注入是最常用的注入方式,这种方式要求依赖者提供公有的构造函数,并将依赖项通过构造函数的方式传入依赖者,完成对依赖项的赋值。 除此之外,还可以通过参数注入的方式,将依赖项注入到Action中,这里使用到FromServices特性: public IActionResult Index([FromServices]ILogger<DefaultController> logger) { throw new NotImplementedException(); } ASP.NET Core 提供了这种支持,但是作者并不推荐这种操作 在视图中注入服务ASP.NET Core 支持将依赖关系注入到视图,代码如下: @using Microsoft.Extensions.Configuration @inject IConfiguration Configuration @{ string myValue = Configuration["root:parent:child"]; ... } 上面的代码演示了将IConfiguration服务注入到视图中,从而实现在视图中读取配置的功能。 有时候将服务注入到视图中会很有用(例如本地化),但是作者也并不是很推荐这种做法,因为这样做容易造成视图和控制器的边界不清晰。 在PageModel中注入服务在PageModel中注入服务的方式,与在Controller中注入服务的方式相似: public class IndexModel : PageModel { private readonly IMyDependency _myDependency; public IndexModel(IMyDependency myDependency) { _myDependency = myDependency; } } 在main方法中获取服务public static void Main(string[] args) { var host = CreateWebHostBuilder(args).Build(); using (var serviceScope = host.Services.CreateScope()) { var services = serviceScope.ServiceProvider; try { var serviceContext = services.GetRequiredService<MyScopedService>(); // Use the context here } catch (Exception ex) { var logger = services.GetRequiredService<ILogger<Program>>(); logger.LogError(ex,"An error occurred."); } } host.Run(); } 在HttpContext.RequestServices中获取服务这种方式不利于测试,不推荐此种用法。 虽然优先推荐通过构造函数的方式注入来获取服务,但是很难避免有些时候需要手工获取服务,在使用手工获取服务的时候,我们应当从HttpContext.RequestServices中获取。 使用第三方依赖注入框架ASP.NET Core内置的依赖注入框架功能有限,当我们想使用第三方框架的特性时,我们可以替换默认依赖注入框架。 ASP.NET Core内置的依赖注入框架未包含的特性:
如果要是用这些功能,我们可以使用第三方框架。本文采用官方文档中的Autofac框架。
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 new AutofacServiceProvider(container); }
public class DefaultModule : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<CharacterRepository>().As<ICharacterRepository>(); } } 参考资料
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- oauth-2.0 – AspNet身份2:自定义OAuth端点响应
- asp.net – 实体框架5在保存时停止运行T4模板文件
- asp.net-mvc – 在ASP.NET MVC组织帐户中访问Azure AD Grap
- ASP.NET MVC 3自定义身份验证/授权
- asp.net-mvc – Asp.Net MVC 4:我们可以设置Layout = null
- asp.net-mvc-3 – 哪里和如何定义我的asp.net MVC 3 web应用
- WeihanLi.Npoi 近期更新
- asp.net-mvc – 使用ASP.NET MVC的基础认证
- ASP.NET Core 开源GitServer 实现自己的GitHub
- 在ASP.NET中,如何防止隐藏字段值的篡改
- asp.net-mvc – AuthorizeAttribute对象的生命周
- asp.net-mvc-4 – 当连接connecttring configSou
- asp.net – 如何基于客户端硬件或其他解决方案实
- asp.net – 如何从进程中慢慢迁移到将Redis用作会
- asp.net – 在什么情况下HttpContext.Current.Se
- asp.net – 在乌龟SVN操作后丢失的IIS_IUSRS权限
- asp.net-mvc – 在控制器的OnException中确定结果
- 我可以创建一个不回发的ASP.NET ImageButton吗?
- asp.net-mvc-4 – 带有返回URL的注销链接(OAuth)
- asp.net-mvc – ASP.NET MVC – 从单个控制器动作