赞
踩
一、配置Autofac替换内置DI
1、安装Nuget包:Autofac.Extensions.DependencyInjection
2、Program.cs中加上
- builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
- builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
- {
- //在这里写注入代码
- });
- public interface IUserService
- {
- public string GetUserName();
- }
- public class UserService:IUserService
- {
- public string GetUserName()
- {
- return "张三";
- }
- }
在上面的ConfigureContainer方法把UserService注入进来,默认是瞬时注入
瞬时注入
containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerDependency();
单例注入
containerBuilder.RegisterType< UserService >().As< IUserService>().SingleInstance();
生命周期注入
containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();
注入试下是否注入成功
调用成功,证明注入成功
三、属性注入
1、把HomeController改成属性注入形式,属性注入有一个问题,就是那些属性需要注入?
全部注入没必要,父类也有很多属性,要按需注入,给属性增加一个自定义特性标识说明需要注入。
- public class HomeController : Controller
- {
- [AutowiredProperty]
- private IUserService userService { get; set; }
- public IActionResult Index()
- {
- string name = userService.GetUserName();
- return View();
- }
- }
2、新增自定义特性类AutowiredPropertyAttribute.cs
- [AttributeUsage(AttributeTargets.Property)]
- //为了支持属性注入,只能打到属性上
- public class AutowiredPropertyAttribute: Attribute
- {
- }
3、增加识别特性类AutowiredPropertySelector.cs
- public class AutowiredPropertySelector : IPropertySelector
- {
- public bool InjectProperty(PropertyInfo propertyInfo, object instance)
- {
- //判断属性的特性是否包含自定义的属性,标记有返回true
- return propertyInfo.CustomAttributes.Any(s => s.AttributeType == typeof(AutowiredPropertyAttribute));
- }
- }
4、因为Controller 默认是由 Mvc 模块管理的,需要把控制器放到IOC容器中,在Program.cs中增加
- //让控制器实例由容器创建
- builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
5、把容器注册到IOC容器,在Program.cs的ConfigureContainer()增加
- //获取所有控制器类型并使用属性注入
- Type[] controllersTypeAssembly = typeof(Program).Assembly.GetExportedTypes()
- .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
- containerBuilder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());
验证:
成功。
四、批量注入
实际项目中那么多需要注入的类,一个个写注册就不太现实了,需要一个可以批量注入的方法。
1、新建三个空接口IScopeDenpendency.cs,ISingletonDenpendency.cs,ITransitDenpendency.cs
- /// <summary>
- /// 瞬时注入
- /// </summary>
- public interface ITransitDenpendency
- {
- }
- /// <summary>
- /// 单例注入标识
- /// </summary>
- public interface ISingletonDenpendency
- {
- }
- /// <summary>
- /// 生命周期注入标识
- /// </summary>
- public interface IScopeDenpendency
- {
- }
2、把上面要注入的类实现上面的接口
3、新增一个IocManager类
- /// <summary>
- /// Ioc管理
- /// </summary>
- public static class IocManager
- {
- /// <summary>
- /// 批量注入扩展
- /// </summary>
- /// <param name="builder"></param>
- /// <param name="assembly"></param>
- public static void BatchAutowired(this ContainerBuilder builder, Assembly assembly)
- {
-
- var transientType = typeof(ITransitDenpendency); //瞬时注入
- var singletonType = typeof(ISingletonDenpendency); //单例注入
- var scopeType = typeof(IScopeDenpendency); //单例注入
- //瞬时注入
- builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(transientType))
- .AsSelf()
- .AsImplementedInterfaces()
- .InstancePerDependency()
- .PropertiesAutowired(new AutowiredPropertySelector());
- //单例注入
- builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(singletonType))
- .AsSelf()
- .AsImplementedInterfaces()
- .SingleInstance()
- .PropertiesAutowired(new AutowiredPropertySelector());
- //生命周期注入
- builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(scopeType))
- .AsSelf()
- .AsImplementedInterfaces()
- .InstancePerLifetimeScope()
- .PropertiesAutowired(new AutowiredPropertySelector());
- }
- }
4、把注入类ConfigureContainer改成
5、防止Program.cs代码过多,建一个Module把注入代码搬走,新建AutofacRegisterModule.cs类把ConfigureContainer的代码移过去
- public class AutofacRegisterModule : Autofac.Module
- {
- protected override void Load(ContainerBuilder builder)
- {
- //获取所有控制器类型并使用属性注入
- Type[] controllersTypeAssembly = typeof(Program).Assembly.GetExportedTypes()
- .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
- builder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());
- //批量自动注入,把需要注入层的程序集传参数,注入Service层的类
- builder.BatchAutowired(typeof(UserService).Assembly);
- //注入其它层的containerBuilder.BatchAutowired(typeof(其它层的任务一个类).Assembly);
- }
- }
ConfigureContainer的代码变成
手动获取实例的场景有静态帮助类中获取实例,例如redisHelper中获取注入的配置文件中的连接字符串
1、在上面的IocManager类中增加
- private static object obj = new object();
- private static ILifetimeScope _container { get; set; }
-
- public static void InitContainer(ILifetimeScope container)
- {
- //防止过程中方法被调用_container发生改变
- if (_container == null)
- {
- lock (obj)
- {
- if (_container == null)
- {
- _container = container;
- }
- }
- }
- }
- /// <summary>
- /// 手动获取实例
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <returns></returns>
- public static T Resolve<T>()
- {
- return _container.Resolve<T>();
- }
2、在Program.cs中增加
3、验证,新建一个DataHelper.cs类
- public class DataHelper
- {
- //手动注入UserService
- private static IUserService userService = IocManager.Resolve<IUserService>();
- public static string GetData()
- {
- return userService.GetUserName();
- }
- }
成功获取到值,证明从容器中获取成功。
六、其它用法
1、不用接口,直接注入实例
- public class UserService :ITransitDenpendency
- {
- public string GetUserName()
- {
- return "张三";
- }
- }
2、一接口多实现
- public class UserService :IUserService
- {
- public string GetUserName()
- {
- return "张三";
- }
- }
-
- public class UserService2 : IUserService
- {
- public string GetUserName()
- {
- return "张三2号";
- }
- }
转自:包子wxl
链接:cnblogs.com/wei325/p/17481596.html
- EOF -
技术群:添加小编微信dotnet999
公众号:dotnet讲堂
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。