在 ASP.NET CORE 3.1 Web API 和来自控制器的消费者服务中配置 Autofac DI 容器

Configure Autofac DI container in ASP.NET CORE 3.1 Web API and consumer service from controller

我需要在 ASP.NET CORE 3.1 Web API 应用程序中配置 Autofac DI 容器,并从 Web API 控制器中的容器调用寄存器 class。我安装 Autofac.Extensions.DependencyInjection (6.0.0) 并尝试在我的 Startup.cs class 中注册容器,但我无法使用服务。另外,我需要在 ConfigureServices(IServiceCollection services) class 中配置容器吗?调试器在命中点 builder.RegisterModule(new IoCConfigurator());

后没有命中 IoCConfigurator() class

Program.cs

 public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

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

Startup.cs

 public class Startup
{
    public IConfiguration Configuration { get; }
    public ContainerBuilder containerBuilder { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
        containerBuilder = new ContainerBuilder();
    }

    public void ConfigureServices(IServiceCollection services)
    {
        ServicesConfigurator.Configure(services, Configuration);
        ConfigureIoC(services, containerBuilder);
    }

    public void ConfigureIoC(IServiceCollection services, ContainerBuilder builder)
    {

        builder.RegisterModule(new IoCConfigurator());
    }

IoCConfigurator.cs

 public class IoCConfigurator: Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<NotifyService>().As<INotificationService>();
        builder.RegisterType<UsersService>().AsSelf();
    }
 }

INotification 接口 & Class

 public interface INotificationService
{
   void notifyUsernameChanged(Users users);
}

   public class NotifyService : INotificationService
{
    public void notifyUsernameChanged(Users users)
    {
        string changedUsername = users.Username;

        Console.WriteLine("Username has changed to ... ");
        Console.WriteLine(changedUsername);
    }
}

用户和用户服务Class

 public class Users
{
    public string Username { get; set; }

    public Users(string username)
    {
        this.Username = username;
    }  
}

public class UsersService
{
    private INotificationService _notificationService;
    public UsersService(INotificationService notificationService)
    {
        this._notificationService = notificationService;
    }

    public void ChangeUsername(Users users, string newUsername)
    {
        users.Username = newUsername;
        _notificationService.notifyUsernameChanged(users);
    }
}

API 我想要 class UserService Class 并从 DI 容器获取引用的控制器

[Authorize]
[Route("txn/v1/[controller]/[action]")]
[ApiController]
public class DashboardController : ControllerBase
{

  [HttpPost("{name}")]
    public ActionResult<HelloMessage> GetMessage(string name)
    {
        // call container here...
        var result = new HelloMessage()
        {
            GivenName = name,
            ReturnMessage = "Dashboard@ Hello, Welcome to Texanite Digital"
        };

        return result;
    }

我是这样设置的。来自命令行:

md autof
cd autof
dotnet new webapi
dotnet add package Autofac.Extensions.DependencyInjection

然后使用 VS 或 VSCode 进行编辑。 Program.cs - 如你所愿:

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

接下来 Startup.cs,忘记 ConfigureIoC,只需注册您 want/need 的服务:

public void ConfigureContainer(ContainerBuilder builder)
    {
        // Register your own things directly with Autofac, like:
        //builder.RegisterModule();
        builder.RegisterType<NotifyService>().As<INotificationService>();
    }

然后在DashboardController.cs中你需要从构造函数中“注入”所需的服务:

public class HelloMessage {
    public string GivenName { get; set; }
    public string ReturnMessage { get; set; }
}

//[Authorize]   Easier without Auth - don't need
[Route("[controller]")]
[ApiController]
public class DashboardController : ControllerBase
{
    private readonly INotificationService _notifyService;

    public DashboardController(INotificationService notifyService)
    {
        _notifyService = notifyService;
    }

    //[HttpPost("{name}")] - easier to test Get
    [HttpGet("{name}")]
    public ActionResult<HelloMessage> GetMessage(string name)
    {
        // call container here...
        _notifyService.notifyUsernameChanged(new Users(name));

        var result = new HelloMessage()
        {
            GivenName = name,
            ReturnMessage = $"Dashboard {name}, Welcome to Texanite Digital"
        };

        return result;
    }
}

我的结果:

控制台输出: 您的 UserService 有点“脱离循环”,但您可以为其添加一个接口并向容器注册并将其添加到控制器的注入服务中。

我可以把整个东西压缩起来,只是不知道把它放在哪里或寄出去...

像我想的那样改变你的代码

Program.cs

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

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

Startup.cs

public class Startup
{
public IConfiguration Configuration { get; }
public ContainerBuilder containerBuilder { get; }

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
    containerBuilder = new ContainerBuilder();
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}