Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Lambda Dependency Injection: Cannot dynamically create an instance of type 'TestDep.Function'. Reason: No parameterless constructor defined

I am trying to use Dependency Injection in my C# Dotnet 6 code to be deployed to AWS Lambda function.

I keep getting this error:

Cannot dynamically create an instance of type 'TestDep.Function'. Reason: No parameterless constructor defined.

I have installed the relevant NuGet packages:

Amazon.Lambda.Annotations;
Microsoft.Extensions.DependencyInjection;

These are my files:

Startup.cs

using System;
using Amazon.Lambda.Annotations;
using Microsoft.Extensions.DependencyInjection;

namespace TestDep
{
    [LambdaStartup]
    public class Startup
    {
        public void ConfigureServices(IServiceCollection serviceCollection)
        {
            serviceCollection.AddTransient<IMyDependency, MyDependency>();

        }
    }
}

My Interface:

namespace TestDep
{
    public interface IMyDependency
    {
        string GetValue(string key);
    }
}

My implementation:

using System;
namespace TestDep
{
    public class MyDependency : IMyDependency
    {
        public MyDependency()
        {
            Value = Guid.NewGuid();
        }

        public Guid Value { get; private set; }

        public string GetValue(string key)
        {
            return $"MyDependency {key} {Value}";

        }
    }
}

my Function:

using Amazon.Lambda.Annotations;
using Amazon.Lambda.Core;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace TestDep;

public class Function
{
    private readonly IMyDependency _myDependencyCtor;
    public Function(IMyDependency myDependency)
    {
        _myDependencyCtor = myDependency;

    }

    /// <summary>
    /// A simple function that takes a string and does a ToUpper
    /// </summary>
    /// <param name="input"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    [LambdaFunction]
    public List<string> FunctionHandler(string a, ILambdaContext context)
    {
        return new List<string>()
        {
            _myDependencyCtor.GetValue("Constructor"),
            a
        };
    }
}

This is my aws-lambda-tools-defaults.json

{
  "Information": [
    "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
    "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
    "dotnet lambda help",
    "All the command line options for the Lambda command can be specified in this file."
  ],
  "profile": "",
  "region": "",
  "configuration": "Release",
  "function-architecture": "x86_64",
  "function-runtime": "dotnet6",
  "function-memory-size": 256,
  "function-timeout": 30,
  "function-handler": "TestDep::TestDep.Function::FunctionHandler"
}

and my serverless.template

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Transform": "AWS::Serverless-2016-10-31",
  "Description": "This template is partially managed by Amazon.Lambda.Annotations (v1.0.0.0).",
  "Resources": {
    "TestDepFunctionFunctionHandlerGenerated": {
      "Type": "AWS::Serverless::Function",
      "Metadata": {
        "Tool": "Amazon.Lambda.Annotations"
      },
      "Properties": {
        "Runtime": "dotnet6",
        "CodeUri": ".",
        "MemorySize": 256,
        "Timeout": 30,
        "Policies": [
          "AWSLambdaBasicExecutionRole"
        ],
        "PackageType": "Zip",
        "Handler": "TestDep::TestDep.Function_FunctionHandler_Generated::FunctionHandler"
      }
    }
  }
}

EDIT:

I couldn't make this work but I found a workaround so that I can still have parameters to inject to make unit testing easy.

public class Function
{
    private readonly IMyDependency _myDependencyCtor;
    public Function()
    {
        var serviceCollection = new ServiceCollection();
        ConfigureServices(serviceCollection);
        var serviceProvider = serviceCollection.BuildServiceProvider();

        // Get Configuration Service from DI system
        _myDependencyCtor = serviceProvider.GetService<IMyDependency>();

    }
    public Function(IMyDependency myDependency)
    {
        _myDependencyCtor = myDependency;

    }
    private void ConfigureServices(IServiceCollection serviceCollection)
    {
        // Register services with DI system
        serviceCollection.AddTransient<IMyDependency, MyDependency>();
    }

    /// <summary>
    /// A simple function that takes a string and does a ToUpper
    /// </summary>
    /// <param name="input"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    [LambdaFunction]
    public List<string> FunctionHandler(string a, ILambdaContext context)
    {
        return new List<string>()
        {
            _myDependencyCtor.GetValue("Constructor"),
            a
        };
    }
}
like image 783
Adilp Avatar asked Oct 16 '25 21:10

Adilp


1 Answers

I had this issue on server, whereas everything was working fine locally.

I fixed it by copying the value of Handler from serverless.template file into function-handler of aws-lambda-tools-default.json file.

function-handler initial "MyLambdaApp::MyLambdaApp.Function::MyAppWithS3"

function-handler after copying from serverless.template Handler "MyLambdaApp::MyLambdaApp.Function_MyAppWithS3_Generated::MyAppWithS3"

like image 152
Vikas Thamke Avatar answered Oct 19 '25 10:10

Vikas Thamke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!