Autofac

简介

通常我们写程序时所有的对象都由我们手动的new出来,这样项目之间互相依赖,各个模块之间耦合严重,当需要修改为其他实现类时非常麻烦。通过IOC可以解除依赖,让代码结构看起来更加合理,并能够提升项目的稳定性和可用性。
Autofac是IOC(Inversion of Control,控制反转)容器的一种,使用IOC容器一般建议基于接口编程。在使用的时候声明接口类型的变量、属性是由容器负责赋值。接口、实现类一般也是定义在单独项目中以减少相互之间的耦合。
基于接口编程:把方法定义到接口中,通过实现类实现接口的方法;

基本使用

安装Autofac:Install-Package Autofac
首先定义一个IAnimal接口和IRun接口,并分别定义Shout和Run方法:

namespace IService
{
    public interface IAnimal
    {
        void Shout();
    }
    // 应该分开写 
    public interface IRun
    {
        void Run();
    }
}

定义Dog、Student实现类实现如下接口:

namespace TestService
{
    public class Dog : IAnimal, IRun
    {
        public void Run()
        {
            Console.WriteLine("小狗在跑");
        }

        public void Shout()
        {
            Console.WriteLine("汪汪汪");
        }
    }
    // 同样要分开写
    public class Student : IRun
    {
        public void Run()
        {
            Console.WriteLine("学生在跑");
        }
    }
}

首先看看Autofac如何注册一个对象的:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Dog>().As<IAnimal>();  // 注册实现类Dog 当请求IAnimal接口的时候返回Dog对象

IContainer container = builder.Build();
IAnimal animal = container.Resolve<IAnimal>();  // 创建IAnimal实现类的对象
animal.Shout();

上例中builder.RegisterType<Dog>().As<IAnimal>(); 只是将Dog注册为IAnimal接口的类型对象,无法通过container.Resolve<IRun>().Run(); 方法调用Dog实现类Run方法。可以替换为builder.RegisterType<Dog>().AsImplementedInterfaces(); 意思是将Dog注册为其所有实现的接口的接口类型对象。这样就可以同时调用Run的方法了。例:

IRun run = container.Resolve<IRun>();
run.Run();

builder可以同时注册多个对象,如:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Dog>().AsImplementedInterfaces();  // 注册Dog对象
builder.RegisterType<Student>().AsImplementedInterfaces();  // 注册Student对象

IContainer container = builder.Build();
IAnimal animal = container.Resolve<IAnimal>();
animal.Shout();

IEnumerable <IRun> runs = container.Resolve<IEnumerable<IRun>>();
foreach (var run in runs)
{
    run.Run();
}

当我们需要注册的对象越多,以上写法就越显的多余,我们可以通过以下方法注册我们需要程序集中的对象:

Assembly[] assemblies = new Assembly[] { Assembly.Load("TestService") };
builder.RegisterAssemblyTypes(assemblies).AsImplementedInterfaces();

如果同一个接口有多个实现类,如IRun接口,container.Resolve<IRun>(); 方法只会返回其中一个类的对象。 如果想返回多个实现类的对象,使用container.Resolve<IEnumerable<IRun>>(); 获取通过foreach遍历即可。

如果一个实现类中定义了其他类型的接口属性,可以在注册的时候加上PropertiesAutowired(),PropertiesAutowired()会自动给属性进行“注入”。 如果可能有多个实现类,还可以声明IEnumerable类型的属性。被只有被Autofac 创建出来的对象才会被“属性自动注入”。

public class Dog : IAnimal
{
    public IEnumerable<IRun> Runs { get; set; }

    public void Shout()
    {
        foreach (var run in Runs)
        {
            run.Run();
        }
        Console.WriteLine("汪汪汪");
    }
}
/* ================================================== */
ContainerBuilder builder = new ContainerBuilder();
Assembly[] assemblies = new Assembly[] { Assembly.Load("TestService") };
builder.RegisterAssemblyTypes(assemblies).AsImplementedInterfaces().PropertiesAutowired();

IContainer container = builder.Build();
IAnimal animal = container.Resolve<IAnimal>();
animal.Shout();

ASP.Net MVC+Autofac

安装Autofac:Install-Package Autofac.Mvc5
首先构造一个Autofac容器的创建者:

// 构造Autofac容器的builder
var builder = new ContainerBuilder();

然后根据自己需要注册内容:

// 注入控制器
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
// 把程序集数组assemblies中所有非抽象的类型注入
Assembly[] assemblies = new Assembly[] { Assembly.Load("TestService") };
builder.RegisterAssemblyTypes(assemblies).Where(t => !t.IsAbstract).AsImplementedInterfaces()
    .PropertiesAutowired();
// 注入特性
builder.RegisterFilterProvider();
// 注入ActionFilter
builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly)
    .Where(t => typeof(ActionFilterAttribute).IsAssignableFrom(t) && !t.IsAbstract)
    .PropertiesAutowired();

通过builder创建容器,并提供给MVC:

// 创建容器
IContainer container = builder.Build();
// 提供给MVC,这样当MVC框架创建Controller等对象时都是从Autofac获取
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

在Autofac容器中注入后,在使用时只用在Controller中声明Service属性即可,Autofac会自动进行“属性注入”。

public class DefaultController : Controller
{
    public IService Service { get; set; }
}

当然,只有通过Autofac帮我们创建的对象并且PropertiesAutowired()后才能给我们自动进行属性的赋值。
有时候我们需要在没有进行注入的地方(如:TestHelper)获取注入的对象,可以通过以下方法:

public class TestHelper
{
    public static void Test()
    {
        IService service = DependencyResolver.Current.GetService<IService>();
    }
}

上面方法指的是在同一个线程中调用,当我们在Quartz等单独线程中,就无法通过DependencyResolver.Current.GetService<IService>();方式获取,需要通过下面的方式获取对象:

IService service;
var container = AutofacDependencyResolver.Current.ApplicationContainer;

using (container.BeginLifetimeScope())
{
    service = container.Resolve<IService>();
}
Autofac对象的生命周期

InstancePerDependency():每次请求Resolve都会返回一个新的、唯一的实例;
SingleInstance():单例,每次都获取相同的共享实例(返回同一个对象);
InstancePerLifetimeScope(): 每个生命周期一个实例;
InstancePerRequest(): ASP.Net MVC 专用,每个请求一个对象;

04-01
<think>好的,我需要回答用户关于Autofac.NET框架中的依赖注入库的使用方法的问题。首先,我需要回忆Autofac的基本概念和核心功能。Autofac是一个流行的IoC容器,用于.NET应用程序中的依赖注入,帮助管理对象的创建和生命周期。 接下来,我要确保覆盖用户可能关心的主要方面,比如基本使用步骤、注册组件的方法、生命周期管理以及与ASP.NET Core的集成。同时,用户提到了引用内容,其中提到了作用域和依赖释放,我需要将这些点整合到回答中,确保引用标识正确。 首先,介绍Autofac是什么,它的作用以及为什么使用它。然后分步骤讲解安装、容器构建、组件注册和解析。这里需要给出代码示例,比如如何创建ContainerBuilder,注册服务,并解析使用。 然后是注册组件的方法,包括类型注册、实例注册和Lambda表达式注册。这部分需要具体例子,比如注册MyService,或者使用Lambda处理复杂初始化。 生命周期管理是关键部分,用户提供的引用[1]提到作用域和依赖释放,我需要详细说明Autofac的InstancePerLifetimeScope,并举例在ASP.NET Core中如何使用,确保依赖项在作用域结束时自动释放。同时,要提醒用户注意长时间存活类中的依赖解析问题,避免内存泄漏,如引用[1]中的警告。 集成ASP.NET Core的部分,需要提到Autofac的扩展库,如何替换默认容器,并在Program.cs中进行配置。给出代码示例,展示AddAutofac()的使用,以及控制器中构造函数注入的例子。 最后,生成相关问题,涵盖高级功能、生命周期比较、与原生容器的区别以及解决循环依赖的方法,这些都能帮助用户进一步学习。 检查是否所有数学公式和独立公式使用正确格式,但看起来这里没有数学内容,可能不需要。然后确保引用正确,引用[1]和引用[2]的相关内容要自然融入回答中,比如作用域释放和构造器注入。 最后通读一遍,确保结构清晰,步骤明确,代码正确,并且引用的位置合适,没有格式错误。这样用户就能系统地了解Autofac的使用方法,并解决可能的疑问。</think>### Autofac依赖注入库在.NET框架中的使用 Autofac.NET生态中广泛使用的轻量级**控制反转IoC)容器**,专注于依赖注入(DI),帮助开发者解耦组件并管理对象生命周期。以下是其核心使用方法: --- #### 1. **基础使用步骤** 1. **安装NuGet包** 通过NuGet安装`Autofac`和`Autofac.Extensions.DependencyInjection`(ASP.NET Core集成需此包): ```bash Install-Package Autofac Install-Package Autofac.Extensions.DependencyInjection ``` 2. **创建容器并注册组件** 使用`ContainerBuilder`注册服务与实现: ```csharp var builder = new ContainerBuilder(); builder.RegisterType<MyService>().As<IMyService>(); // 注册接口与实现 builder.RegisterInstance(new Logger()).As<ILogger>(); // 注册单例实例 var container = builder.Build(); ``` 3. **解析依赖** 通过容器解析服务: ```csharp using var scope = container.BeginLifetimeScope(); var service = scope.Resolve<IMyService>(); // 解析服务实例 ``` --- #### 2. **组件注册方式** - **类型注册** ```csharp builder.RegisterType<EmailService>().As<INotificationService>(); ``` - **实例注册**(单例) ```csharp var cache = new MemoryCache(); builder.RegisterInstance(cache).As<ICache>(); ``` - **Lambda注册**(复杂初始化) ```csharp builder.Register(c => new ConfigReader(c.Resolve<IConfig>())) .As<IConfigReader>(); ``` --- #### 3. **生命周期管理** Autofac通过生命周期作用域(Lifetime Scope)控制对象释放,避免内存泄漏[^1]: - **瞬时实例**(每次解析新对象) ```csharp builder.RegisterType<TransientService>().InstancePerDependency(); ``` - **作用域实例**(同一作用域内单例) ```csharp builder.RegisterType<ScopedService>().InstancePerLifetimeScope(); ``` - **单例实例**(全局唯一) ```csharp builder.RegisterType<SingletonService>().SingleInstance(); ``` --- #### 4. **与ASP.NET Core集成** 在ASP.NET Core中替换默认DI容器为Autofac: ```csharp var builder = WebApplication.CreateBuilder(args); builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()) .ConfigureContainer<ContainerBuilder>(container => { container.RegisterModule<MyApplicationModule>(); // 模块化注册 }); ``` **控制器依赖注入示例**: ```csharp public class HomeController : Controller { private readonly IMyService _service; public HomeController(IMyService service) { _service = service; // 通过构造函数自动注入 } } ``` --- #### 5. **注意事项** - **作用域释放**:通过`BeginLifetimeScope()`创建的作用域结束时,其解析的所有瞬时/作用域实例会自动释放[^1]。 - **单例陷阱**:若单例服务依赖作用域服务,需使用`ILifetimeScope`参数或`InstancePerMatchingLifetimeScope`限定作用域[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值