Autofac lazy property injection

心不动则不痛 提交于 2019-12-17 21:23:33

问题


I'm trying to inject business logic implementations into web API base controller. Somehow property in base controller is always null.

Also how can I do lazy injection?

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>();
}

Interface, implementation and base controller:

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; }
}

回答1:


Controllers aren't resolved by the DI framework by default. You need to add AddControllerAsServices to have them be resolved by the DI of your choice.

From this GitHub issue:

Hi,

Maybe I'm wrong but as I tested deeply (and checked Mvc source code), Controllers are not resolved from IServiceProvider, but only constructor arguments of them are resolved from IServiceProvider.

Is that by design? I'm very suprised. Because, I'm using a different DI framework which supports property injection. And I can not use property injection since Controller instances are not requested from IServiceProvider.

Have you added AddControllersAsServices in your Startup (https://github.com/aspnet/Mvc/blob/ab76f743f4ee537939b69bdb9f79bfca35398545/test/WebSites/ControllersFromServicesWebSite/Startup.cs#L37)

The example above quoted for future reference.

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>();
}

As for the second part of your question: I don't think it's possible to have lazy instantiation via IoC container at all. Best fit for you is to create a factory class and inject the factory rather than the concrete service.

But usually you don't need lazy instantiation anyways, the instantiation of services should be fast. If it's not, you probably doing some funky stuff in the constructor (connecting somewhere, or doing other long running operations), which is an anti-pattern.



来源:https://stackoverflow.com/questions/39556405/autofac-lazy-property-injection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!