Azure / azure-webjobs-sdk

Azure WebJobs SDK
MIT License
738 stars 358 forks source link

Registering a Service with Default/Optional Constructor Argument(s) throws Exception #2865

Open GregoryLeeWhite opened 2 years ago

GregoryLeeWhite commented 2 years ago

An exception occurs when starting durable functions that register a dependency containing a constructor argument with a default value.

Repro steps

  1. Register a service with a default/optional constructor argument.

    public MyService(IOtherDependency otherDependency, int optionalArgument = 15)
    {
    _otherDependency = otherDependency;
    _optionalArgument = optionalArgument;
    }
  2. Register dependency. services.AddTransient<IMyService, MyService>();

  3. Run durable function project.

Expected behavior

Should start up and register dependency properly.

Actual behavior

Executed 'SendLane' (Failed, Id=4ebe8f67-57f2-401f-885d-6848de522d00, Duration=92334ms)
[2022-05-05T16:33:45.565Z] Anonymously Hosted DynamicMethods Assembly: Object reference not set to an instance of an object.
[2022-05-05T16:33:45.570Z] bdf1adfc1c27429cb8f43413ac5cb715: Function 'SendLane (Activity)' failed with an error. Reason: System.NullReferenceException: Object reference not set to an instance of an object.
[2022-05-05T16:33:45.570Z]    at lambda_method499(Closure , IResolverContext )
[2022-05-05T16:33:45.571Z]    at DryIoc.Container.ResolveAndCacheDefaultFactoryDelegate(Type serviceType, IfUnresolved ifUnresolved) in D:\a\1\s\src\WebJobs.Script.WebHost\DependencyInjection\DryIoc\Container.cs:line 224
[2022-05-05T16:33:45.571Z]    at DryIoc.Container.DryIoc.IResolver.Resolve(Type serviceType, IfUnresolved ifUnresolved) in D:\a\1\s\src\WebJobs.Script.WebHost\DependencyInjection\DryIoc\Container.cs:line 195
[2022-05-05T16:33:45.572Z]    at Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedServiceProvider.GetService(Type serviceType) in D:\a\1\s\src\WebJobs.Script.WebHost\DependencyInjection\ScopedServiceProvider.cs:line 25
[2022-05-05T16:33:45.572Z]    at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
[2022-05-05T16:33:45.573Z]    at lambda_method498(Closure , IServiceProvider , Object[] )
[2022-05-05T16:33:45.573Z]    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
[2022-05-05T16:33:45.573Z]    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
[2022-05-05T16:33:45.574Z]    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
[2022-05-05T16:33:45.574Z]    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
[2022-05-05T16:33:45.575Z]    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
[2022-05-05T16:33:45.575Z]    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 776
[2022-05-05T16:33:45.576Z]    at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsync(IFunctionInstance functionInstance, CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 101. IsReplay: False. State: Failed. HubName: TestHubName. AppName: . SlotName: . ExtensionVersion: 2.7.0. SequenceNumber: 7. TaskEventId: 0

Known workarounds

Using null as the default value.

public MyService(IOtherDependency otherDependency, int? optionalArgument = null)
{
    _otherDependency = otherDependency;
    _optionalArgument = optionalArgument ?? 15;
}

Related information

This was initially reported in Issue #180 in the DryIoc repository. Based on this comment, DryIoc v5.0.2 was released today and resolves the issue on their end.

I'm not sure which version, nor what package this relates to.
Here are the WebJobs/Azure Function packages that I currently reference.

Eli-Black-Work commented 2 years ago

I think this issue's title got messed up; it's just "Object" 😄

GregoryLeeWhite commented 2 years ago

I think this issue's title got messed up; it's just "Object" 😄

Woops! Updated the title. Thanks for the heads up 😅

Eli-Black-Work commented 2 years ago

Haha, thanks ^_^