【问题标题】:Autofac lazy property injectionAutofac 惰性属性注入
【发布时间】:2017-01-26 03:41:13
【问题描述】:

我正在尝试将业务逻辑实现注入 Web API 基本控制器。不知何故,基本控制器中的属性总是null

还有怎么做惰性注入?

Startups.cs

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    var containerBuilder = new ContainerBuilder();
    containerBuilder.RegisterType<ViewBusinessLogic>().As<IViewBusinessLogic>().
        PropertiesAutowired();
    containerBuilder.Populate(services);

    var container = containerBuilder.Build();

    return container.Resolve<IServiceProvider>();
}

接口、实现和基本控制器:

public interface IViewBusinessLogic
{
    IEnumerable<dynamic> GetView(Guid viewId);
}

public class ViewBusinessLogic : BusinessLogic, IViewBusinessLogic
{
    public IEnumerable<dynamic> GetView(Guid viewId)
    {
        return new List<dynamic>
        {
            new { Test = "Test1" },
            new { Test = "Test2" }
        };
    }
}

public abstract class BaseController : Controller
{
    public IViewBusinessLogic ViewBusinessLogic { get; }
}

【问题讨论】:

  • 这不是 Autofac 问题,而是 ASP.NET Core 问题。 如果没有 AddControllersAsServices,属性注入在任何其他 DI 提供程序中都不起作用 - 因此我的标题编辑。由于标题不正确和拒绝更新为更准确的标题而被否决的问题。

标签: asp.net dependency-injection asp.net-core autofac


【解决方案1】:

默认情况下,DI 框架不解析控制器。您需要添加 AddControllerAsServices 以让您选择的 DI 解决它们。

来自this GitHub issue

嗨,

也许我错了,但是当我深入测试(并检查了 Mvc 源代码)时,控制器不是从 IServiceProvider 解析的,但只有它们的构造函数参数是从 IServiceProvider 解析的。

这是设计使然吗?我很惊讶。因为,我使用的是不同的支持属性注入的 DI 框架。而且我不能使用属性注入,因为 IServiceProvider 没有请求控制器实例。

你是否在你的 Startup 中添加了AddControllersAsServices (https://github.com/aspnet/Mvc/blob/ab76f743f4ee537939b69bdb9f79bfca35398545/test/WebSites/ControllersFromServicesWebSite/Startup.cs#L37)

上面引用的例子供将来参考。

public void ConfigureServices(IServiceCollection services)
{
    var builder = services
        .AddMvc()
        .ConfigureApplicationPartManager(manager => manager.ApplicationParts.Clear())
        .AddApplicationPart(typeof(TimeScheduleController).GetTypeInfo().Assembly)
        .ConfigureApplicationPartManager(manager =>
        {
            manager.ApplicationParts.Add(new TypesPart(
              typeof(AnotherController),
              typeof(ComponentFromServicesViewComponent),
              typeof(InServicesTagHelper)));

            manager.FeatureProviders.Add(new AssemblyMetadataReferenceFeatureProvider());
        })

        // This here is important
        .AddControllersAsServices()
        .AddViewComponentsAsServices()
        .AddTagHelpersAsServices();

    services.AddTransient<QueryValueService>();
    services.AddTransient<ValueService>();
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

至于您问题的第二部分:我认为根本不可能通过 IoC 容器进行延迟实例化。最适合您的是创建一个工厂类并注入工厂而不是具体服务。

但通常无论如何您都不需要惰性实例化,服务的实例化应该很快。如果不是,您可能在构造函数中做了一些时髦的事情(连接某处,或执行其他长时间运行的操作),这是一种反模式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-01
    • 2012-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多