Azure / Azure/azure-functions-host
Resolution of dependency fails on types with default arguments in constructors
- Dominant language
- C#
- Stars
- 2k
- Forks
- 482
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 36
Description
#### Investigative information
Please provide the following:
- Function App version (1.0 or 2.0): 2.0
#### Repro steps
Steps to reproduce:
- Create the following types hierarchy
```csharp
interface IA
{
void DoA();
}
class A : IA
{
public void DoA()
{
}
}
public interface IB
{
void DoB();
}
class B : IB
{
private readonly IA _ia;
private readonly int _param;
public B(IA ia, int param = 0)
{
_ia = ia;
_param = param;
}
public void DoB()
{
}
}
```
- Add following function `Startup`:
```csharp
internal class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
=> builder.Services.AddScoped().AddScoped();
}
```
- Create the following function:
```csharp
public class Function1
{
private readonly IB _b;
public Function1(
IB b) => _b = b;
[FunctionName(nameof(Function1Run))]
public async Task Function1Run([QueueTrigger("queue", Connection = "AzureWebJobsStorage")]
string queuedEvents) => _b.DoB();
}
```
- Run the function app.
#### Expected behavior
The dependency resolves correctly with a default argument in the constructor.
#### Actual behavior
NullReferenceException is thrown. Available stack trace:
```
at lambda_method(Closure )
at DryIoc.Scope.TryGetOrAdd(ImMap`1 items, Int32 id, CreateScopedValue createValue, Int32 disposalOrder) in C:\azure-functions-host\src\WebJobs.Script.WebHost\DependencyInjection\DryIoc\Container.cs:line 7840
at DryIoc.Scope.GetOrAdd(Int32 id, CreateScopedValue createValue, Int32 disposalOrder) in C:\azure-functions-host\src\WebJobs.Script.WebHost\DependencyInjection\DryIoc\Container.cs:line 7825
at DryIoc.CurrentScopeReuse.GetScopedOrSingleton(IResolverContext r, Int32 id, CreateScopedValue createValue, Int32 disposalIndex) in C:\azure-functions-host\src\WebJobs.Script.WebHost\DependencyInjection\DryIoc\Container.cs:line 8157
at lambda_method(Closure , IResolverContext )
at DryIoc.Container.ResolveAndCacheDefaultFactoryDelegate(Type serviceType, IfUnresolved ifUnresolved) in C:\azure-functions-host\src\WebJobs.Script.WebHost\DependencyInjection\DryIoc\Container.cs:line 224
at DryIoc.Container.DryIoc.IResolver.Resolve(Type serviceType, IfUnresolved ifUnresolved) in C:\azure-functions-host\src\WebJobs.Script.WebHost\DependencyInjection\DryIoc\Container.cs:line 195
at Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedServiceProvider.GetService(Type serviceType) in C:\azure-functions-host\src\WebJobs.Script.WebHost\DependencyInjection\ScopedServiceProvider.cs:line 25
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
at lambda_method(Closure , IServiceProvider , Object[] )
at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IServiceProvider serviceProvider) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs:line 37
at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IFunctionInstanceEx functionInstance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs:line 32
at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.<>c__DisplayClass1_1.<.ctor>b__0(IFunctionInstanceEx i) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs:line 20
at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.Create(IFunctionInstanceEx functionInstance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs:line 26
at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.CreateInstance(IFunctionInstanceEx functionInstance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs:line 44
at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ParameterHelper.Initialize() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 846
at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsyncCore(IFunctionInstanceEx functionInstance, CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 117
```
#### Known workarounds
Do not use value types with default value as constructor parameters.
#### Related information
Provide any related information
* Programming language used - C#
Contributor guide
Research direction
Start by reproducing the constructor-resolution failure from the C# hierarchy and inspect the DryIoc.Container.cs stack locations, especially lines 7840 and 7825, along with ScopedServiceProvider.cs. Trace how the default constructor argument is handled and verify that the dependency resolves without a NullReferenceException, ideally with regression coverage in the existing dependency-injection tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, csharp
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100