.NET7 中Autofac依赖注入整合多层,项目中可直接用
阅读原文时间:2023年08月11日阅读:4

一、配置Autofac替换内置DI

1.安装Nuget包:Autofac.Extensions.DependencyInjection

2.Program.cs中加上

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer(containerBuilder =>
{
//在这里写注入代码

});

二、构造函数注入

新建IUserService,类UserService

public interface IUserService
{
public string GetUserName();
}

public class UserService:IUserService
{
public string GetUserName()
{
return "张三";
}
}

在上面的ConfigureContainer方法把UserService注入进来,默认是瞬时注入

瞬时注入:containerBuilder.RegisterType().As().InstancePerDependency();;

单例注入:containerBuilder.RegisterType().As().SingleInstance();

生命周期注入: containerBuilder.RegisterType().As().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());

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

///

/// 瞬时注入 ///
public interface ITransitDenpendency
{
}
  /// /// 单例注入标识 ///
public interface ISingletonDenpendency
{
}
   /// /// 生命周期注入标识 ///
public interface IScopeDenpendency
{
}

2.把上面要注入的类实现上面的接口

3.新增一个IocManager类

///

/// Ioc管理 ///
public static class IocManager
{
/// /// 批量注入扩展 ///
///
///
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;
}
}
}
}
///

/// 手动获取实例 ///
///
///
public static T Resolve()
{
return _container.Resolve();
}

2.在Program.cs中增加

3.验证,新建一个DataHelper.cs类

public class DataHelper
{
//手动注入UserService
private static IUserService userService = IocManager.Resolve();
public static string GetData()
{
return userService.GetUserName();
}
}

成功获取到值,证明从容器中获取成功。

六、其它用法

public class UserService :ITransitDenpendency
{
public string GetUserName()
{
return "张三";
}
}

public class UserService :IUserService
{
public string GetUserName()
{
return "张三";
}
}

public class UserService2 : IUserService
{
public string GetUserName()
{
return "张三2号";
}
}

TRANSLATE with x

English

Arabic

Hebrew

Polish

Bulgarian

Hindi

Portuguese

Catalan

Hmong Daw

Romanian

Chinese Simplified

Hungarian

Russian

Chinese Traditional

Indonesian

Slovak

Czech

Italian

Slovenian

Danish

Japanese

Spanish

Dutch

Klingon

Swedish

English

Korean

Thai

Estonian

Latvian

Turkish

Finnish

Lithuanian

Ukrainian

French

Malay

Urdu

German

Maltese

Vietnamese

Greek

Norwegian

Welsh

Haitian Creole

Persian

 

TRANSLATE with

COPY THE URL BELOW

Back

EMBED THE SNIPPET BELOW IN YOUR SITE

Enable collaborative features and customize widget: Bing Webmaster Portal

Back