C# 依赖注入
依赖注入1. 什么是依赖注入?? 我们创建一个SkiCardController需要应用程序中的一些其他服务才能处理查看,创建和编辑的请求。具体来说,他用SkiCardContext访问数据,用UserManager
访问当前用户的信息,用IAuthorizationService检查当前用户是否有权限编辑或者查看所有请求。
public class SkiCardController:Controller { private readonly SkiCardContext _SkiCardContext; private readonly UserManager<ApplicationUser> _UserManager; private readonly IAuthorizationService _AuthorizationService; public SkiCardController() { _SkiCardContext = new SkiCardContext(new DbContextOptions<SkiCardContext>()); _UserManager = new UserManager<ApplicationUser>(); _AuthorizationService = new DefaultAuthorizationService(); } } ?? 这些看起来还算简单,但实际上这段代码是无法通过编译的。首先,我们没有为SkiCardContext指定数据库或者连接字符串,所以他没有正确创建 public UserManager(IUserStore<TUser> store,IOption<IdentityOptions> optionsAccessor,IPasswordHasher<TUser> passwordHasher,IEnumerable<IUserValidator<TUser>> userValidator,IEnumerable<IPasswordValidator<IUser>> passwordValidator,ILookupNormalizer keyNormalizer,IdentityErrorDescriber errors,IServiceProvider service,ILogger<UserManager<TUser>> logger) { // ... } ?? 那么,我们的SkiCardController现在还需要知道如何去创建这些服务。 2. 使用服务容易解析依赖?? 依赖注入是用来解析依赖项的一种常见模式。使用依赖注入之后,创建和管理类的实例的职责就转交给某个容器。此外,每一个类都需要声明他所依赖的其他类。然后容器就可以在运行期间解析这些依赖项,并按需传递。依赖注入模式是控制反转( public class SkiCardController : Controller { private readonly SkiCardContext _SkiCardContext; private readonly UserManager<ApplicationUser> _UserManager; private readonly IAthorizationService _AuthorizationService; public SkiCardController(SkiCardContext skiCardContext,UserManager<ApplicationUser> userManager,IAthorizationService autherizationService) { _SkiCardContext = skiCardContext; _UserManager = userManager; _AuthorizationService = autherizationService } } ?? 构造函数注入能够清晰地体现给定的某个类所需要的依赖。甚至连编译器都会为我们提供帮助,因为不传递必需的类无法创建SkiCardController。正如我们之前所说,这种方法的主要好处是能够让单元测试更加简单。
ASP.NET Core 中的依赖注入?? ASP.NET Core提供了容器的基本实现,原生支持构造函数注入。在应用程序启动时,可以在Startup类的ConfigureService方法中注册服务。 public void ConfigureService(IServiceCollection service) { // add service here. } ?? 哪怕在最简单的 使用内置容器?? 你要做的首先是添加 service.AddDbContext<ApplicationUserContext>(options=>options.UserSqlServer(Configuration.GetConnectionString("DefaultConnection"))); service.AddDbContext<SkiCardContext>(options=>options.UserSqlServer(Configuration.GetConnectionString("DefaultConnection"))); service.AddDbContext<PassContext>(options=>options.UserSqlServer(Configuration.GetConnectionString("DefaultConnection"))); service.AddDbContext<PassTypeContext>(options=>options.UserSqlServer(Configuration.GetConnectionString("DefaultConnection"))); service.AddDbContext<RestoreContext>(options=>options.UserSqlServer(Configuration.GetConnectionString("DefaultConnection"))); ?? 其他需要添加的框架功能还包括用于认证和授权的Identity、启用强类型配置的Options以及启用路由、控制器和其他所有内置功能的MVC。 service.AddIdentity<ApplicationUser,IdentityRole>() .AddEntityFrameworkStore<ApplicationUserContext>() .AddDefaultTokenProviders(); service.AddOptions(); service.AddMvc(); ?? 下一步是注册你编写的应用程序服务或者第三方类库中包含的服务。确保任意控制器所需的任意服务都正确地注册了。在注册应用服务时,一定要考虑该服务的生命周期。
?? 使用 service.AddSingleton<IAuthorizationHandler,EditSkiCardAuthorizationHandler>(); service.AddTransient<IEmailSender,AuthMessageSender>(); service.AddTransient<ISmsSender,AuthMessageSender>(); service.AddScoped<ICsrInformationService,CsrInformationService>(); ?? 随着应用程序服务逐渐增多,可以通过创建扩展方法来简化ConfigureService方法。举例来说,如果你的应用程序拥有许多需要注册的IAuthorizationHandler类,你就可以创建一个AddAuthorizationHandlers扩展方法。 public static void AddAuthorizationHandlers(this IServiceCollection services) { services.AddSingleton<IAuthorizationHandler,EditSkiCardAuthorizationHandler>(); // Add other authorization handlers } ?? 将服务添加到
services.AddScoped<IScrInformationService,CsrInformationService>() 使用第三方容器?? public IServiceProvider ConfigureServices(IServiceCollectioin services) { // Add framework services service.AddDbContext<ApplicationUserContext>(options=>options.UserSqlServer(Configuration.GetConnectionString("DefaultConnection"))); service.AddDbContext<SkiCardContext>(options=>options.UserSqlServer(Configuration.GetConnectionString("DefaultConnection"))); service.AddDbContext<PassContext>(options=>options.UserSqlServer(Configuration.GetConnectionString("DefaultConnection"))); service.AddDbContext<PassTypeContext>(options=>options.UserSqlServer(Configuration.GetConnectionString("DefaultConnection"))); service.AddDbContext<RestoreContext>(options=>options.UserSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity<ApplicationUser,IdentifyRole>() .AddEntityFrameworkStores<ApplicationUserContext>() .AddDefaultTokenProviders(); services.AddOptions(); services.AddMvc(); // Now register our services with Autofac container var builder = new ContainerBuilder(); builder.RegisterType<CsrInformationService>().As<ICsrInformationService>(); builder.Populate(services); var container = builder.Build(); // Create the IServiceProvider based on the container. return new AutofaceServiceProvider(container); } ?? 这个实例相当简单, var currentAssembly = Assembly.GetEntryAssembly(); builder.RegisterAssemblyTypes(currentAssembly) .Where(t => t.IsAssignableTo<IAuthorizationHandler>()) .As<IAuthorizationHandler>(); ?? public class AuthorizationHandlerModule:Module { protected override void Load(ContainerBuilder builder) { var currentAssembly = Assembly.GetEntryAssembly(); builder.RegisterAssemblyTypes(currentAssembly) .Where(t=>t.IsAssignableTo<IAuthorizationHandler>()) .As<IAuthorizationHandler>(); } } ?? 在Startup.ConfigureServices中加载模块 builder.RegisterModule(new AuthorizationHandlerModule()); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |