Azure / Azure/azure-functions-host

Resolution of dependency fails on types with default arguments in constructors

Open
#5,418 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.