Autofac入门与替代ASP.NET CO re、 ABP依赖注入容器

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: Autofac入门与替代ASP.NET CO re、 ABP依赖注入容器

Autofac 的使用


我们在 .NET Core 控制台程序中进行测试和实践。


1,简单的实践


首先我们添加一个接口以及实现:

public interface IMyService { }
    public class MyService : IMyService { }


然后在 Main 方法中注册以及构建容器:

class Program
    {
        private static IContainer Container;
        static void Main(string[] args)
        {
            // 创建容器构建器
            var builder = new ContainerBuilder();
            // 注册组件
            builder.RegisterType<MyService>().As<IMyService>();
            // ...
            // 构建容器
            Container = builder.Build();
        }
    }


我们则可以这样使用:

public static void Test()
        {
            // 生命周期管理
            using (ILifetimeScope scope = Container.BeginLifetimeScope())
            {
                // 获取实例
                IMyService myService = scope.Resolve<IMyService>();
            }
        }


.AS() 用于暴露组件的服务。

这就是 Autofac 的简单使用。

下面我们来讨论更详细的使用方法以及实践。


2,注册组件


前面我们通过 ContainerBuilder 对象来注册组件并且告诉容器有哪些组件暴露了哪些服务。


组件的注册方式有很多种,前面我们使用了反射的方法去注册,传递一个泛型参数进去:

.RegisterType<MyService>()


或者通过类型(Type)进行注入:

builder.RegisterType(typeof(MyService)).As<IMyService>();


当然,通过反射注册的组件,它会自动为你注入相应的构造函数。

你也可以通过 UsingConstructor 方法,要求容器实例化组件时,使用哪一个构造函数:

builder.RegisterType<MyComponent>()
       .UsingConstructor(typeof(ILogger), typeof(IConfigReader));


我们也可以提前将实例注册进去:

MyService t = new MyService();
            builder.RegisterInstance(t).As<IMyService>();


这样就会生成一个单例应用。

不过,因为 RegisterInstance(t) 会保留对 t 的引用,也就是说将这个实例注册到容器的实例中。


当然你可以使用 Lambda 表达式树来 new :

builder.Register(c => new MyService()).As<IMyService>();


这样可以避免外部有引用。

如果你不想这样,可以使用 ExternallyOwned 方法,这样就会生成一个新的实例到容器中。如果你会 AutoMapper ,这样会很容易理解。

builder.RegisterInstance(t).As<IMyService>().ExternallyOwned();


3,Lambda 注册组件


如果一个类型的构造函数依赖于另一个接口,那么这种类型作为组件注册,就会复杂一些,我们可以使用 Lambda 表达式来注册组件。


有以下几个接口和类型:

public interface IA { }
    public class A : IA { }
    public interface IB { }
    public class B : IB
    {
        private IA _a;
        public B(IA a)
        {
            _a = a;
        }
    }


那么我们可以先注册 A 类型,再注册 B 类型:

builder.RegisterType<A>().As<IA>();
            builder.Register(c => new B(c.Resolve<IA>()));


当然,这里使用表达式来介绍方便性。你也可以这样使用:

builder.RegisterType<A>().As<IA>();
            builder.RegisterType<B>().As<IB>();

实例化 B 类型时,会自动为其注入构造函数。


4,注册泛型


如果要对泛型类型进行注册:

public interface IA { }
    public class A<T> : IA { }


则可以使用 RegisterGeneric 来注册泛型组件:

builder.RegisterGeneric(typeof(A<>)).As<IA>();


当然,如果 IA 也是泛型的话,应该使用 .As(typeof(IA))


5,属性注入


注册组件时,使用 PropertiesAutowired 方法,那么容器在生成实例时,会自动注入属性。

有以下类型:

public interface IA { }
    public class A : IA { }
    public interface IB { }
    public class B : IB
    {
        public IA A { get; set; }
    }


注册:

builder.RegisterType<A>().As<IA>();
            builder.RegisterType<B>().PropertiesAutowired().As<IB>();

那么,容器会自动给 B 类型的属性注入依赖。

当然,这样会为类型的每一个属性注入依赖。


如果我们只是想为某个属性注入的话,可以这样 使用 WithProperty 方法,例如:

builder.RegisterType<B>().WithProperty("A",new A()).As<IB>();


6,解析服务

注册组件后,调用 Build() 方法生成了容器(IContainer)。

然后使用 Resolve 方法在其生命周期内解析服务。


参考前面的示例如下:

using (ILifetimeScope scope = Container.BeginLifetimeScope())
            {
                // 获取实例
                IMyService myService = scope.Resolve<IMyService>();
            }


要注意的是,实例是从生命周期中解析(ILifetimeScope scope),而不是从容器中(IContainer)中解析。

如果想知道一个服务是否已经被注册,我们可以使用 ResolveOptional()TryResolve() 方法。


using (ILifetimeScope scope = Container.BeginLifetimeScope())
            {
                IB b;
                // 获取实例
                if (scope.TryResolve<IB>(out b))
                {
                }
            }


在解析时,可以传递参数,这样可以控制容器生成实例时,使用能够构造函数实例化类型。

Autofac提供了多种不同的参数匹配机制:

  • NamedParameter - 通过名称匹配目标参数
  • TypedParameter - 通过类型匹配目标参数 (需要匹配具体类型)
  • ResolvedParameter - 灵活的参数匹配


示例如下:

namespace AutofacTest
{
    public interface IA { }
    public class A : IA
    {
        public A(string a, string b) { Console.WriteLine($"a = {a}, b = {b}"); }
    }
    class Program
    {
        private static IContainer Container;
        static void Main(string[] args)
        {
            // 创建容器构建器
            var builder = new ContainerBuilder();
            builder.RegisterType<A>().As<IA>();
            // 构建容器
            Container = builder.Build();
            Test();
        }
        public static void Test()
        {
            // 生命周期管理
            using (ILifetimeScope scope = Container.BeginLifetimeScope())
            {
                IA b = scope.Resolve<IA>(new NamedParameter("a", "测试"), new NamedParameter("b", "测试"));
            }
        }
    }


或者改成:

IA b = scope.Resolve<IA>(new TypedParameter(typeof(string), "测试"), new TypedParameter(typeof(string), "测试"));


另外,Autofac 还支持多种关系的服务解析,其种类如下:


7,生命周期


关于生命周期,你可以参考:https://autofaccn.readthedocs.io/zh/latest/lifetime/index.html

前面我们看到,要获取实例,使用了


using (ILifetimeScope scope = Container.BeginLifetimeScope())
{
}


BeginLifetimeScope 创建一个生命周期作用域,生命周期的作用域是可释放的并且可以追踪组件的释放。

你可以使用 Dispose() 或者 using{} 形式进行生命周期释放。


你也可以:

using (ILifetimeScope scope = Container.BeginLifetimeScope())
            {
                using (ILifetimeScope sc = scope.BeginLifetimeScope())
                {
                }
            }


8,实例作用域

实例的作用域决定了对于暴露出来的同一个服务的实例如何在多个请求之间共享。组件的作用域是在注册组件是决定的,然后显式地调用 Resolve() 返回地示例,就会出现具体的行为(单例等)。


8.1 一个依赖一个实例

在 .NET 默认的依赖注入框架中,称为 'transientfactory ,对于每个请求,每次返回的都是不一样的实例。Autofac 默认就是这种模式。


你也可以使用 InstancePerDependency 显式声明:

builder.RegisterType<Worker>().InstancePerDependency();


8.2 单一实例

SingleInstance 方法可以注册组件为单一实例:

builder.RegisterType<Worker>().SingleInstance();


8.3 生命周期作用域实例

使用 InstancePerLifetimeScope可以设置组件在一个生命周期作用域内,获取到的实例都是同一个。


另外,层叠的生命周期作用域也是不同的,例如下面的示例中,结果是 True,False

using (ILifetimeScope scope = Container.BeginLifetimeScope())
            {
                IA b = scope.Resolve<IA>();
                IA bb = scope.Resolve<IA>();
                Console.WriteLine(b == bb);
                using (ILifetimeScope sc = scope.BeginLifetimeScope())
                {
                    IA bbb = sc.Resolve<IA>();
                    Console.WriteLine(b == bbb);
                }
            }


另外 Autofac 还有其它方法的作用域管理,请点击链接了解: https://autofaccn.readthedocs.io/zh/latest/lifetime/instance-scope.html


9,Autofac 其它需要学习的知识

Autofac 是非常厉害的框架,本文只是挑入门基础部分讲解,其它自由度高一些的复杂一些的知识点例如:

需要查看文档学习,这里不再赘述。


ASP.NET Core


ASP.NET Core 中,2.x 和 3.x 的差异比较多,这里只以 3.x 作为示例。


1,默认依赖注入


ASP.NET Core 中,默认的依赖注入,可以使用 ConfigureServices 方法,在此方法中注册即可。

例如:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<IA, A>();
        }


2,使用 Autofac


如果要在 ASP.NET Core 中使用 Autofac 作为依赖注入容器,则还需要安装名为 Microsoft.Extensions.DependencyInjection.Abstractions 的 Nuget 包。


然后在 Program 的 Host 中加上

.UseServiceProviderFactory(new AutofacServiceProviderFactory())


示例如下:

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
               .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });


然后在 Startup 类中,加上 ConfigureContainer 方法,然后在此方法中注册需要的组件:

public void ConfigureContainer(ContainerBuilder builder)
        {
            builder.RegisterType<A>().As<IA>();
        }


最后在 ConfiguraServices 方法中添加:

services.AddOptions();


即可使用 Autofac 作为 ASP.NET Core 依赖注入容器。

完整代码:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions();
            services.AddControllers();
        }
        public void ConfigureContainer(ContainerBuilder builder)
        {
            builder.RegisterType<A>().As<IA>();
        }


ABP


首先要求你添加了一个 ASP.NET Core 程序,然后配置 ABP ,引入相应的包。可以参考 https://docs.abp.io/zh-Hans/abp/latest/Getting-Started-AspNetCore-Application


ABP 中,默认也是使用 ConfigureServices 直接注入即可,使用示例:

public class AppModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddTransient<IA, A>();
        }
    }


context.Services 即为 IServiceCollection 对象。

当然,ABP 也可以使用 Autofac 作为依赖注入容器。

ABP 中要使用 Autofac,需要引用 Volo.Abp.Autofac 包。

然后在模块中加上 [DependsOn(typeof(AbpAutofacModule))] 特性。


[DependsOn(typeof(AbpAutofacModule))]
    public class AppModule : AbpModule{}


然后在 Startup 中的 ConfiguraServices 方法中,添加 ABP 模块, 并且设置使用 Autofac。

public void ConfigureServices(IServiceCollection services)
        {
            services.AddApplication<BasicAspNetCoreApplication.AppModule>(options=>
            {
                options.UseAutofac();
            });
        }
相关文章
|
2月前
|
开发框架 算法 中间件
ASP.NET Core 中的速率限制中间件
在ASP.NET Core中,速率限制中间件用于控制客户端请求速率,防止服务器过载并提高安全性。通过`AddRateLimiter`注册服务,并配置不同策略如固定窗口、滑动窗口、令牌桶和并发限制。这些策略可在全局、控制器或动作级别应用,支持自定义响应处理。使用中间件`UseRateLimiter`启用限流功能,并可通过属性禁用特定控制器或动作的限流。这有助于有效保护API免受滥用和过载。 欢迎关注我的公众号:Net分享 (239字符)
64 1
|
2月前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
60 5
|
2月前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
59 3
|
3月前
|
Kubernetes Cloud Native 开发者
云原生入门:从容器到微服务
本文将带你走进云原生的世界,从容器技术开始,逐步深入到微服务架构。我们将通过实际代码示例,展示如何利用云原生技术构建和部署应用。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和启示。
|
3月前
|
Kubernetes Cloud Native 云计算
云原生入门:Kubernetes 和容器化基础
在这篇文章中,我们将一起揭开云原生技术的神秘面纱。通过简单易懂的语言,我们将探索如何利用Kubernetes和容器化技术简化应用的部署和管理。无论你是初学者还是有一定经验的开发者,本文都将为你提供一条清晰的道路,帮助你理解和运用这些强大的工具。让我们从基础开始,逐步深入了解,最终能够自信地使用这些技术来优化我们的工作流程。
|
3月前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
64 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
3月前
|
Kubernetes Linux Docker
容器化技术Docker入门与实践
容器化技术Docker入门与实践
85 0
|
3月前
|
Kubernetes Docker 容器
掌握Docker容器化技术:从入门到实战
掌握Docker容器化技术:从入门到实战
57 0
|
5月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
114 0
|
5月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
72 7