Asp.Net Core 依赖注入(内置与Autofac)
1.asp.net core 内置依赖注入
1.1框架结构如图
因为测试我建了两个类库,Core.IServices(接口) Core.Services(实现),里面新建了接口与实现。
1.2 服务注册
注册服务有三种方法,每个都有不同的生命周期
暂时(Transient):每次获取这个服务的实例时都要创建一个这个服务的实例
作用域(Scoped):这种类型的服务实例保存在当前依赖注入容器(IServiceProvider)上。在同作用域,服务每个请求只创建一次
单例(Singleton):第一次请求时就创建,以后每次请求都是使用的相同的实例.
服务注册是在Staup类里面的ConfigureServices方法中,如图
点击查看代码
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IMenuService, MenuService>();
services.AddTransient<IUserService, UserService>();
services.AddControllers();
}
点击查看代码
public void ConfigureServices(IServiceCollection services)
{
//services.AddTransient<IMenuService, MenuService>();
//services.AddTransient<IUserService, UserService>();
var IServices = Assembly.Load("Core.IServices").GetTypes().Where(w => w.Name.Contains("Service"));
var Services = Assembly.Load("Core.Services").GetTypes().Where(w => w.Name.Contains("Service"));
foreach (var item in IServices)
{
var name = item.Name.Substring(1);
var Service = Services.FirstOrDefault(w => w.Name.Contains(name));
if (Service != null)
{
services.AddTransient(item, Service);
}
}
services.AddControllers();
}
1.3构造函数注入
在Controller中,使用构造函数进行注入,并调用相应的实现方法,如图
点击查看代码
[Route("api/test")]
public class TestAPiController
{
private readonly IMenuService _menuService;
private readonly IUserService _userService;
public TestAPiController(IMenuService menuService,
IUserService userService)
{
this._menuService = menuService;
this._userService = userService;
}
/// <summary>
/// 获取菜单名称
/// </summary>
/// <returns></returns>
[Route("getName"),HttpGet]
public string GetName()
{
return this._menuService.GetMenuName();
}
/// <summary>
/// 获取用户信息
/// </summary>
/// <returns></returns>
[Route("getUserInfo"), HttpGet]
public string GetUserInfo()
{
return this._userService.GetUserInfo();
}
}
1.4 启动项目,测试接口,如图
2.Autofac
2.1首先需要安装两个包,使用NuGet安装,或者在程序包管理控制台输入一下命令安装
Autofac
Autofac.Extension.DependencyInjection
2.2在Program.cs添加Autofac服务提供工厂,如图
点击查看代码
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).UseServiceProviderFactory(new AutofacServiceProviderFactory());
2.3 服务注册,Autofac 是在ConfigureContainer方法中注册的,默认是构造函数注入,如图
点击查看代码
public void ConfigureContainer(ContainerBuilder builder)
{
//单个服务注册
// builder.RegisterType<MenuService>().As<IMenuService>();
// builder.RegisterType<IUserService>().As<IUserService>();
//服务项目程序集
Assembly service = Assembly.Load("Core.Services");
//服务接口项目程序集
Assembly iservice = Assembly.Load("Core.IServices");
builder.RegisterAssemblyTypes(iservice,service).Where(n => n.FullName.EndsWith("Service") && !n.IsAbstract)
.InstancePerLifetimeScope().AsImplementedInterfaces();
}
2.4属性注入
新增自定义特性类AutowiredPropertyAttribute.cs
点击查看代码
[AttributeUsage(AttributeTargets.Property)]
public class AutowiredPropertyAttribute : Attribute
{
}
点击查看代码
/// <summary>
/// IPropertySelector:查看属性上是否标记某一个特性
/// </summary>
public class AutowiredPropertySelector : IPropertySelector
{
public bool InjectProperty(PropertyInfo propertyInfo, object instance)
{
//判断属性的特性是否包含自定义的属性,标记有返回true
return propertyInfo.CustomAttributes.Any(s => s.AttributeType == typeof(AutowiredPropertyAttribute));
}
}
点击查看代码
services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
实例化控制器所有需要的组件后添加.PropertiesAutowired(),该方法需要指定需要去实现指定哪些属性,因此需要为需要的属性添加特性进行标识,再通过选择器进行过滤,将添加了特性的属性注入实现。
点击查看代码
///注册所有控制器,实例化需要的所有组件
Type[] controllersTypeAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
builder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());
////单个服务注册
builder.RegisterType<MenuService>().As<IMenuService>().PropertiesAutowired();
点击查看代码
///注册所有控制器,实例化需要的所有组件
Type[] controllersTypeAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
builder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());
////单个服务注册
// builder.RegisterType<MenuService>().As<IMenuService>().PropertiesAutowired();
//服务项目程序集
Assembly service = Assembly.Load("Core.Services");
//服务接口项目程序集
Assembly iservice = Assembly.Load("Core.IServices");
builder.RegisterAssemblyTypes(iservice, service).Where(n => n.FullName.EndsWith("Service") && !n.IsAbstract)
.InstancePerLifetimeScope().AsImplementedInterfaces().PropertiesAutowired();
// builder.RegisterModule(new AutofacModule());
点击查看代码
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
//builder.Register(c => new MenuService())
// .As<IMenuService>()
// .InstancePerLifetimeScope();
//服务项目程序集
System.Reflection.Assembly service = System.Reflection.Assembly.Load("Core.Services");
//服务接口项目程序集
System.Reflection.Assembly iservice = System.Reflection.Assembly.Load("Core.IServices");
builder.RegisterAssemblyTypes(iservice, service).Where(n => n.FullName.EndsWith("Service") && !n.IsAbstract)
.InstancePerLifetimeScope().AsImplementedInterfaces().PropertiesAutowired();
}
}
在Controller属性注入
控制器中添加接口属性并标记特性
点击查看代码
[Route("api/test")]
public class TestAPiController:Controller
{
[AutowiredProperty]
private IMenuService _menuService { get; set; }
[AutowiredProperty]
private IUserService _userService { get; set; }
/// <summary>
/// 获取菜单名称
/// </summary>
/// <returns></returns>
[Route("getName"),HttpGet]
public string GetName()
{
return this._menuService.GetMenuName();
}
[Route("getUserInfo"),HttpGet]
public string GetUserinfo()
{
return _userService.GetUserInfo();
}
}
参考地址 :点击进入
无穷的伟大,也是从“0”开始的