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
    {
    }
增加识别特性类AutowiredPropertySelector.cs

点击查看代码
/// <summary>
    /// IPropertySelector:查看属性上是否标记某一个特性
    /// </summary>
   public class AutowiredPropertySelector : IPropertySelector
    {
        public bool InjectProperty(PropertyInfo propertyInfo, object instance)
        {
            //判断属性的特性是否包含自定义的属性,标记有返回true
            return propertyInfo.CustomAttributes.Any(s => s.AttributeType == typeof(AutowiredPropertyAttribute));
        }
    }
因为Controller 默认是由 Mvc 模块管理的,需要把控制器放到IOC容器中,在Startup.cs的ConfigureServices中增加

点击查看代码
services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
把容器注册到IOC容器,在Startup.cs的ConfigureContainer()增加

实例化控制器所有需要的组件后添加.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());
也可根据模块注册,新建一个AutofacModule类,继承Module,重写load方法,如图

点击查看代码
  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();
        }

    }
启动项目,测试接口,测试成功

参考地址 :点击进入

posted @ 2022-07-05 21:44  万万万W  阅读(529)  评论(0编辑  收藏  举报