ASP.NET CORE Field Injection
NetCore Container
(add some features to the default container).NAutowired
in the constructor.NetCore
default Container
, which means you can still add services to Container
using IServiceCollection
in Startup
. And use NAutowired
to resolve dependencies.NAutowired
and NAutowired.Core
in the nuget.NAutowired
package should only be referenced in the web project, and the NAutowired.Core
package is referenced in projects that need to add features.ASP.NET Core 3.0
ASP.NET Core 6.0
By default, when ASP.NET Core
generates Controller
, dependencies in the Controller
constructor are resolved from the container, but the controller is not resolved from the container, which results in:
Controller
is handled by the framework, not the lifetime of the requestController
constructor is handled by the request lifetimeController
use Field Injection
won’t workYou must use the AddControllersAsServices
method to register the Controller
as a Service so that the Controller
can use the Field Injection
when resolve.
Use AddControllersAsServices
in Startup.cs
and replace IControllerActivator
as NAutowiredControllerActivator
.
IControllerActivator
implementation with NAutowiredControllerActivator
in Startup.cs
public void ConfigureServices(IServiceCollection services) {
//register controllers as services
services.AddControllers().AddControllersAsServices();
//replace `IControllerActivator` implement.
services.Replace(ServiceDescriptor.Transient<IControllerActivator, NAutowiredControllerActivator>());
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
//Add FooService to container.
services.AddScoped<FooService>();
//Add IBarService implements to container.
services.AddScoped<IBarService, MyBarService1>();
services.AddScoped<IBarService, MyBarService2>();
}
[Route("api/[controller]")]
[ApiController]
public class FooController : ControllerBase {
//Use Autowired injection.
[Autowired]
private readonly FooService fooService;
//Also supports IEnumerable<T> injection.
[Autowired]
private readonly IEnumerable<IBarService> barServices;
[HttpGet]
public ActionResult<string> Get() {
return fooService == null ? "failure" : "success";
}
[HttpPost]
public ActionResult<string> Baz() {
return barServices?.Count > 0 ? "success" : "failure";
}
}
Filter
public class Startup {
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
//Add Filter to container.
services.AddScoped<AuthorizationFilter>();
}
}
//Use ServiceFilter like ASP.NET CORE ServiceFilter.
[NAutowired.Attributes.ServiceFilter(typeof(AuthorizationFilter))]
public class FooController : ControllerBase {
}
public class AuthorizationFilter : IAuthorizationFilter {
[Autowired]
private readonly FooService fooService;
public void OnAuthorization(AuthorizationFilterContext context) {
System.Console.WriteLine($"{fooService.ToString()} in filter");
return;
}
}
public class Startup {
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
//add config to ioc container
services.Configure<SnowflakeConfig>(Configuration.GetSection("Snowflake"));
}
}
public class FooController : ControllerBase {
//use autowired get configuration
[Autowired]
private IOptions<SnowflakeConfig> options { get; set; }
[HttpGet("snowflake")]
public IActionResult GetSnowflakeConfig()
{
return Ok(options.Value);
}
}
SnowflakeConfig.cs
public class SnowflakeConfig
{
public int DataCenter { get; set; }
public int Worker { get; set; }
}
appsettings.json
{
"Snowflake": {
"DataCenter": 1,
"Worker": 1
}
}
NET Core
Console >= 3.0Srartup.cs
file and inherit from NAutowired.Core.Startup
public class Startup : NAutowired.Core.Startup
{
[Autowired]
private readonly FooService fooService;
//Program start up func
public override void Run(string[] args)
{
System.Console.WriteLine(fooService.Foo());
System.Console.ReadLine();
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
ConsoleHost.CreateDefaultBuilder(new List<string> { "assemblyName" }, args).Build().Run<Startup>();
//You can also let NAutowired use the IServiceCollection you passed
/*
ConsoleHost.CreateDefaultBuilder(() => {
var serviceDescriptors = new ServiceCollection();
serviceDescriptors.AddTransient<FooService>();
return serviceDescriptors;
}, new List<string> { "NAutowiredConsoleSample" }, args).Build().Run<Startup>();
*/
}
}
[Autowired(Type)]
method [Route("api/[controller]")]
[ApiController]
public class FooController : ControllerBase {
//Inject a specific instance.
[Autowired(typeof(FooService))]
private readonly IFooService fooService;
[HttpGet]
public ActionResult<string> Get() {
return fooService == null ? "failure" : "success";
}
}
NAutowired
provides the AutoRegisterDependency(assemblyName)
method for automatic container injection. This way you don't need to add the type to the container one by one in Startup.cs
public class Startup {
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
//services.AddScoped<FooService>();
//Use automatic injection.
services.AutoRegisterDependency(new List<string> { "NAutowiredSample" });
}
}
[Service] [Repository] [Component] [ServiceFilter]
attribute tag class, these classes will be added to the container when AutoRegisterDependency
is executed //The default Lifetime value is Scoped
[Service]
//Lifetime to choose the life cycle of dependency injection
//[Service(Lifetime.Singleton)]
public class FooService {
}
[Service(implementInterface: typeof(IService))]
//injection interface to container like services.AddScoped(typeof(IService), typeof(FooService));
public class FooService: IService {
}
NAutowired
will automatically scan all classes under the assembly configured by the AutoRegisterDependency(assemblyName)
method, and inject the class with the [Service] [Repository] [Component] [ServiceFilter]
property into the container.
NAutowired
provides WithAutowired
、GetServiceWithAutowired
extension methods,which can obtain services from containers and automatically resolve their [Autowired]
dependencies. It's particularly convenient when you need to manually obtain services or resolve existing instances.services.AddSingleton(sp =>
{
var foo = sp.GetServiceWithAutowired<IFooService>();
return foo.Create();
});