I am using Azure Function
v2. Here is my function that uses the constructor injection:
public sealed class FindAccountFunction
{
private readonly IAccountWorkflow m_accountWorkflow;
private readonly IMapper m_mapper;
private readonly ILogger m_logger;
public FindAccountFunction(ILogger logger, IMapper mapper, IAccountWorkflow accountWorkflow)
{
m_logger = logger;
m_mapper = mapper;
m_accountWorkflow = accountWorkflow;
}
[FunctionName("FindAccount")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, Verbs.Get, Route = "v1/accounts/")] HttpRequest httpRequest, ILogger logger)
{
// Do stuff.
}
}
I am declaring all the dependencies that I want to inject into my Azure Function in the Startup class that derives from IWebJobsStartup
:
public sealed class Startup : IWebJobsStartup
{
public void Configure(IWebJobsBuilder webJobsBuilder)
{
// Registers the application settings' class.
webJobsBuilder.Services.AddSingleton<IApplicationSettings, ApplicationSettings>();
// ** Registers the ILogger instance **
// ** ?? **
// Registers the IMapper instance for the contracts.
var mapperConfiguration = new MapperConfiguration(cfg => cfg.AddProfile(new MyProfile()));
webJobsBuilder.Services.AddSingleton(mapperConfiguration.CreateMapper());
// Registers custom services.
webJobsBuilder.Services.AddTransient<IStorageService, StorageService>();
webJobsBuilder.Services.AddTransient<IAccountWorkflow, AccountWorkflow>();
}
}
The Azure Function calls other injected services that do depends on the ILogger as well, such as the IAccountWorkflow
:
public sealed class AccountWorkflow : IAccountWorkflow
{
public AccountWorkflow(ILogger logger, IStorageService storageService)
{
if(logger is null)
throw new ArgumentNullException();
}
}
The problem is that the DI is unable to find any ILogger
implementation and fails to resolve services since a null ILogger
is injected.
Question
How can I setup the injection of the ILogger
in IWebJobsStartup
?
Reference Use dependency injection in .NET Azure Functions
Registering services
To register services, you can create a configure method and add components to an
IFunctionsHostBuilder
instance. The Azure Functions host creates anIFunctionsHostBuilder
and passes it directly into your configured method.To register your configure method, you must add an assembly attribute that specifies the type for your configure method using the
FunctionsStartup
attribute.
So in this case
[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]
namespace MyNamespace {
public class Startup : FunctionsStartup {
public override void Configure(IFunctionsHostBuilder builder) {
// ** Registers the ILogger instance **
builder.Services.AddLogging();
// Registers the application settings' class.
//...
//...omitted for brevity
}
}
}
I believe since you have access to the service collection, you should be able to add logging to it
public void Configure(IWebJobsBuilder webJobsBuilder) {
// ** Registers the ILogger instance **
webJobsBuilder.Services.AddLogging();
//OR
//webJobsBuilder.Services.AddLogging(builder => {
// //...
//});
// Registers the application settings' class.
//...
//...removed for brevity
}
and having anILoggerFactory
in the Function's constructor.
//...
//Ctor
public FindAccountFunction(ILoggerFactory loggerFactory, IMapper mapper, IAccountWorkflow accountWorkflow) {
m_logger = loggerFactory.CreateLogger<FindAccountFunction>();
m_mapper = mapper;
m_accountWorkflow = accountWorkflow;
}
//...
I managed to resolve this problem:
Injecting into my class as below:
MyClass.cs:
public class MyClass
{
private readonly ILogger<MyClass> _logger;
public MyClass(ILogger<MyClass> logger)
{
_logger = logger;
}
}
Startup.cs:
[assembly: FunctionsStartup(typeof(Namespace.Startup))]
namespace Namespace {
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddLogging();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With