Setter Injection not working (Core 3.0)
See original GitHub issueCreate a default .Net core 3.0 web app
Nuget
Lamar
4.0.0
Nuget
Lamar.Microsoft.DependencyInjection
4.0.2
Program:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseLamar()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Startup:
public void ConfigureContainer(ServiceRegistry services)
{
services.Scan(scanner =>
{
scanner.TheCallingAssembly();
scanner.WithDefaultConventions();
scanner.SingleImplementationsOfInterface();
});
services.Policies.SetAllProperties(y => y.OfType<ISetter>());
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// debug
var container = (IContainer)app.ApplicationServices;
var plan = container.Model.For<WeatherForecastController>().Default.DescribeBuildPlan();
Console.WriteLine(plan); // this shows both inline AND setter in the build plan
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Some POCO + Interface:
public interface ISetter
{
}
public class Setter : ISetter
{
}
Controller:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[SetterProperty] // doesn't help
public ISetter setter { get; set; } // always null, with, or without attribute
...derp...
public WeatherForecastController(ISetter _setter) // this works
{
}
}
I’ve tried every flavor of setter / property injection, nothing seems to work. I had this working in StructureMap though.
Side note: when using a public abstract class
without a constructor, the build plan throws an error. I thought this was my original problem but when I did a vanilla setter injection test as described above, it seems to just be broken.
Example:
public abstract class BaseController : ControllerBase
{
// even when setup properly these are always null.
public IMediator _mediator { get; set; }
public IHubContext<LogHub> _logHubContext { get; set; }
public IConfiguration _config { get; set; }
Issue Analytics
- State:
- Created 4 years ago
- Comments:14 (7 by maintainers)
Top Results From Across the Web
Inject and @Autowired not working whereas ...
1 Answer 1 · 1. Use a setter as per your example and remove the @Inject. This is the simplest approach since you...
Read more >Understanding Dependency Injection in .NET Core
This tutorial will try to clarify the various Dependency Injection concepts and will introduce you to the support provided by .NET Core. The...
Read more >Dependency Injection in ASP.NET Core
ASP.NET Core injects objects of dependency classes through constructor or method by using built-in IoC container. Built-in IoC Container. ASP.NET Core framework ...
Read more >3.4.1 Dependency injection
The Spring team generally advocates setter injection, because large numbers of constructor arguments can get unwieldy, especially when properties are optional.
Read more >Setter Injection | Lamar
If setter injection is not working for you, try to look at the WhatDoIHave() output and type scanning. Lamar can inject dependencies into...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@jeremydmiller I figured it out. Definitely not a Lamar issue, just an MVC setup issue. You may want to add this to your asp.net Core 3.x docs
services.AddMvc().AddControllersAsServices();
For some reason adding AddControllersAsServices(); fixes it.
So I did some investigation. I could use a breadcrumb, you may know where to look. I can see that Jasper is creating the correct code to inject the setter, I get this from DescribeBuildPlan() specific to WeatherForecastController:
WhatDidIScan() includes my only assembly and WhatDoIHave() does show ISetter. All of this is looking good.
I did a direct test on the container in Startup.cs, testing as so:
var controller = container.GetInstance<WeatherForecastController>();
This worked as expected, the public property APublicSetterProperty was set and not null.I noticed when debugging the Lamar code when I call DescribeBuildPlan() or GetInstance<T>() or GetService(Type serviceType)
The code will call down into ContructorInstance.cs and into the findSetters() method:
This is what I would expect. However, when I comment out my calls to DescribeBuildPlan, GetInstance and GetService it looks like whatever is resolving the MVC Controller WeatherForecastController it is not following the same or similar code paths within IoC\Scope.cs. It looks like the bootstrapping to the Asp Core dependency resolver is not calling into Lamar to instance the MVC Controller? It looks like most of this happens in IoC\Scope.cs, but I am not able to locate where Asp Core calls into Lamar to instance Controller classes, do you know where that entry point is?
Side note, I may be wrong on some of this as I am just learning the code.