.NET 7 中 Autofac 依賴(lài)注入整合多層,項(xiàng)目中可直接用
2、Program.cs中加上
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
//在這里寫(xiě)注入代碼
});
二、構(gòu)造函數(shù)注入
新建IUserService,類(lèi)UserService
public interface IUserService
{
public string GetUserName();
}
public class UserService:IUserService
{
public string GetUserName()
{
return "張三";
}
}
在上面的ConfigureContainer方法把UserService注入進(jìn)來(lái),默認(rèn)是瞬時(shí)注入
瞬時(shí)注入
containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerDependency();
單例注入
containerBuilder.RegisterType< UserService >().As< IUserService>().SingleInstance();
生命周期注入
containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();
注入試下是否注入成功
調(diào)用成功,證明注入成功
三、屬性注入
1、把HomeController改成屬性注入形式,屬性注入有一個(gè)問(wèn)題,就是那些屬性需要注入?
全部注入沒(méi)必要,父類(lèi)也有很多屬性,要按需注入,給屬性增加一個(gè)自定義特性標(biāo)識(shí)說(shuō)明需要注入。
public class HomeController : Controller
{
[AutowiredProperty]
private IUserService userService { get; set; }
public IActionResult Index()
{
string name = userService.GetUserName();
return View();
}
}
2、新增自定義特性類(lèi)AutowiredPropertyAttribute.cs
[AttributeUsage(AttributeTargets.Property)]
//為了支持屬性注入,只能打到屬性上
public class AutowiredPropertyAttribute: Attribute
{
}
3、增加識(shí)別特性類(lèi)AutowiredPropertySelector.cs
public class AutowiredPropertySelector : IPropertySelector
{
public bool InjectProperty(PropertyInfo propertyInfo, object instance)
{
//判斷屬性的特性是否包含自定義的屬性,標(biāo)記有返回true
return propertyInfo.CustomAttributes.Any(s => s.AttributeType == typeof(AutowiredPropertyAttribute));
}
}
4、因?yàn)镃ontroller 默認(rèn)是由 Mvc 模塊管理的,需要把控制器放到IOC容器中,在Program.cs中增加
//讓控制器實(shí)例由容器創(chuàng)建
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
5、把容器注冊(cè)到IOC容器,在Program.cs的ConfigureContainer()增加
//獲取所有控制器類(lèi)型并使用屬性注入
Type[] controllersTypeAssembly = typeof(Program).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
containerBuilder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());
驗(yàn)證:
成功。
四、批量注入
實(shí)際項(xiàng)目中那么多需要注入的類(lèi),一個(gè)個(gè)寫(xiě)注冊(cè)就不太現(xiàn)實(shí)了,需要一個(gè)可以批量注入的方法。
1、新建三個(gè)空接口IScopeDenpendency.cs,ISingletonDenpendency.cs,ITransitDenpendency.cs
/// <summary>
/// 瞬時(shí)注入
/// </summary>
public interface ITransitDenpendency
{
}
/// <summary>
/// 單例注入標(biāo)識(shí)
/// </summary>
public interface ISingletonDenpendency
{
}
/// <summary>
/// 生命周期注入標(biāo)識(shí)
/// </summary>
public interface IScopeDenpendency
{
}
2、把上面要注入的類(lèi)實(shí)現(xiàn)上面的接口
3、新增一個(gè)IocManager類(lèi)
/// <summary>
/// Ioc管理
/// </summary>
public static class IocManager
{
/// <summary>
/// 批量注入擴(kuò)展
/// </summary>
/// <param name="builder"></param>
/// <param name="assembly"></param>
public static void BatchAutowired(this ContainerBuilder builder, Assembly assembly)
{
var transientType = typeof(ITransitDenpendency); //瞬時(shí)注入
var singletonType = typeof(ISingletonDenpendency); //單例注入
var scopeType = typeof(IScopeDenpendency); //單例注入
//瞬時(shí)注入
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、把注入類(lèi)ConfigureContainer改成
5、防止Program.cs代碼過(guò)多,建一個(gè)Module把注入代碼搬走,新建AutofacRegisterModule.cs類(lèi)把ConfigureContainer的代碼移過(guò)去
public class AutofacRegisterModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
//獲取所有控制器類(lèi)型并使用屬性注入
Type[] controllersTypeAssembly = typeof(Program).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
builder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());
//批量自動(dòng)注入,把需要注入層的程序集傳參數(shù),注入Service層的類(lèi)
builder.BatchAutowired(typeof(UserService).Assembly);
//注入其它層的containerBuilder.BatchAutowired(typeof(其它層的任務(wù)一個(gè)類(lèi)).Assembly);
}
}
ConfigureContainer的代碼變成
五、手動(dòng)獲取實(shí)例
手動(dòng)獲取實(shí)例的場(chǎng)景有靜態(tài)幫助類(lèi)中獲取實(shí)例,例如redisHelper中獲取注入的配置文件中的連接字符串
1、在上面的IocManager類(lèi)中增加
private static object obj = new object();
private static ILifetimeScope _container { get; set; }
public static void InitContainer(ILifetimeScope container)
{
//防止過(guò)程中方法被調(diào)用_container發(fā)生改變
if (_container == null)
{
lock (obj)
{
if (_container == null)
{
_container = container;
}
}
}
}
/// <summary>
/// 手動(dòng)獲取實(shí)例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T Resolve<T>()
{
return _container.Resolve<T>();
}
2、在Program.cs中增加
3、驗(yàn)證,新建一個(gè)DataHelper.cs類(lèi)
public class DataHelper
{
//手動(dòng)注入U(xiǎn)serService
private static IUserService userService = IocManager.Resolve<IUserService>();
public static string GetData()
{
return userService.GetUserName();
}
}
成功獲取到值,證明從容器中獲取成功。
六、其它用法
1、不用接口,直接注入實(shí)例
public class UserService :ITransitDenpendency
{
public string GetUserName()
{
return "張三";
}
}
2、一接口多實(shí)現(xiàn)
public class UserService :IUserService
{
public string GetUserName()
{
return "張三";
}
}
public class UserService2 : IUserService
{
public string GetUserName()
{
return "張三2號(hào)";
}
}
轉(zhuǎn)自:包子wxl
鏈接:cnblogs.com/wei325/p/17481596.html
