Advanced Serverless AWS Lambda  Dependency Injection
Tags: csharp, aws, dotnet, serverless
Published: 2019-04-27 06:54:06

---
title: Advanced Serverless AWS Lambda  Dependency Injection
published: true
tags: Csharp,AWS,dotnet,serverless
canonical_url: https://garywoodfine.com/serverless-aws-lambda-dependency-injection/
---

I have previously provided a simple example of how to introduce [simple dependency injection and configuration to your Serverless Framework AWS Lambda](https://dev.to/gary_woodfine/simple-dependency-injection-in-aws-lambda-5cgj-temp-slug-4239809), In this post, we’ll dive a little deeper and learn how to completely implement dependency injection and how to layout your Lambda Project.

The issue when creating projects using frameworks and templates is that it often guides developers into thinking that the only way too can implement solutions is by following the guidelines provided by the project template.

The truth is when it comes to the _Serverless Framework_ the only thing that is of any real importance is the YAML file, which is primarily used to create Cloud Formation script to create and manage the AWS resources to be used by your Lambda and the deployment script. When it comes to the actual code and structure of your lambda project and the code it contains, it really doesn’t care.

When generating a new _AWS Lambda_ project, the _Serverless Framework_ generates only the simplest project possible. A project which has hardly any features that most .net developers are typically used too and it falls on to them to implement all the features they need.

In this post, I will walk you through how to implement full-blown Dependency Injection, Configuration and even make use of IHost functionality in your AWS Lambda projects. The only restriction you’ll face in AWS Lambda Projects is that at the time of writing you are limited to using **.net core 2.1**

{% github garywoodfine/HelloConfiguration %}

### Start a new AWS Lambda Project

If you haven’t used or unfamiliar with the Serverless Framework then I suggest you read [Getting started with .NET Core and the Serverless Framework.](https://dev.to/gary_woodfine/getting-started-with-net-core-and-the-serverless-framework-1kge-temp-slug-5669462)it will guide you through installing, provide a basic understanding of Serverless Framework and generate a typical project. I will assume you already have this knowledge for the remainder of this tutorial.

> Information

> We will be continuing to develop on the code presented in[Simple Dependency 
> Injection In AWS Lambda](https://dev.to/gary_woodfine/simple-dependency-
> injection-in-aws-lambda-5cgj-temp-slug-4239809)

Let's generate a new Serverless project

```bash
sls create -t  aws-csharp -p HelloConfiguration -n Threenine.ConfigTest

```

The reality is we could just delete the .net project created and start again, because the only things of use for us in the generated project is the `serverless.yml` , `build.sh` but we’ll work with what we’ve got!

We’re going to do a fit of refactoring here to tidy up the generated project to better suit our conventions etc. In a future post, I will provide details on how you can create your own custom Project Templates with the _Serverless Framework_ so you don’t have to do this Boilerplate grunt work on every project you start.

In the first instance, we will want to rename our assembly to more closely match its purpose. When you’re engaging in Micro-services Development and developing many Lambdas you don’t really want 100’s of lambdas all named `aws-csharp` and a default namespace of `AwsDotnetCsharp`, it really doesn’t describe the component you’re developing and is counter-intuitive to the [Philosophy of Software Design](https://garywoodfine.com/philosophy-of-software-design)

The process to renaming your Assembly and setting the default namespace is as normal in whichever IDE or Text Editor you’re using. I predominantly use [Jet Brains Rider – A fast & powerful cross-platform .NET IDE](https://www.jetbrains.com/rider/) , so my process will be slightly different to most. However, there are few important edits to make to your `serverless.yml` to ensure you don’t implement breaking changes.

```js

service: Hello-Configuration

provider:
  name: aws
  runtime: dotnetcore2.1

package:
  individually: true

functions:
  hello:
    handler: HelloConfiguration::Threenine.ConfigTest.Handler::Hello

 
    package:
      artifact: bin/release/netcoreapp2.1/hello.zip


```

You’ll notice I simply edit line 12 to represent the fact I have renamed my Assembly to `HelloConfiguration` and my Namespace for my project is now `Threenine.ConfigTest.` For the purpose of this Demo code, this will suffice, I just wanted to highlight that you can edit these project files to better suit your needs.

### Add a StartUp class

In the sample code for [Simple Dependency Injection In AWS Lambda](https://dev.to/gary_woodfine/simple-dependency-injection-in-aws-lambda-5cgj-temp-slug-4239809) we followed some pretty bad coding practices and created one class that did everything, which is not SOLID and could cause all sorts of maintenance nightmares so we do some refactoring on that class and split core functional components into their own classes. I always have the [principles of Adaptive Code](hhttps://garywoodfine.com/adaptive-code/) in mind when developing!

So lets add a new class and by convention we’ll call this `StartUp.cs`

We are going to slightly refactor our `ILambdaConfiguration` and `LambdaConfiguration` to make use of `IConfigurationRoot` which represents the root of an IConfiguration hierarchy

```c#
public interface  ILambdaConfiguration
    {
        IConfigurationRoot Configuration { get; }
    }

```

```c#
public class LambdaConfiguration : ILambdaConfiguration
    {
        public static IConfigurationRoot Configuration  => new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .Build();


        IConfigurationRoot ILambdaConfiguration.Configuration => Configuration;
    }

```


Our new startUp class is going to be the location where we wire up our dependency and configuration data that our application is going to use.

So before we actually do that, we’ll have to create our services and do some more refactoring of our application. In my example I deleted the `Handler.cs` file created a new directory named _Functions_ and created a new class in that directory named `Speak.cs`

For the sake of demo, I created an additional Directory named Services and created an interface of `ISpeakService` and a class called `SpeakService`

```c#
public interface ISpeakService
    {
        string Greeting { get; }
    }


```

```c#

public class SpeakService : ISpeakService
    {
        private readonly Greeting _greeting;
        public SpeakService(IOptions<Greeting> hello)
        {
            _greeting = hello.Value;
        }

        public string Greeting => _greeting.Message;
    }

```

You’ll notice that the `SpeakService` with make use of the [Options pattern](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.1)provide a mechanism to validate configuration data . We also seem to using a class called Greeting, let's go ahead and create that class

```c#
[JsonObject("greeting")]
    public class Greeting
    {
        [JsonProperty("message")]
        public string Message { get; set; }
    }


```

We can now wire up our dependencies in our StartUp class

```c#
public class StartUp
    {
        public static IServiceCollection Container => ConfigureServices(LambdaConfiguration.Configuration);


        private static IServiceCollection ConfigureServices(IConfigurationRoot root)
        {
            
            var services = new ServiceCollection();
            
            //Wire up all your dependencies here
            services.Configure<Greeting>(options =>
                root.GetSection("greeting").Bind(options));
            
            services.AddTransient<ISpeakService, SpeakService>();
            
            return services;
        }
    }


```

In our Speak.cs class we’ll now make use of all our dependencies. You’ll notice that we will create 2 class constructors one of which will take in an IServiceProvider and the other will instantiate this class by initialising out StartUp class.

Our greet method will then Get a service we from our IOC container and use it. We make use of the [ServiceProvider.GetService](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.serviceprovider.getservice?view=aspnetcore-2.1) method to get the service object of the specified type.

```c#

public class Speak
    {
        private readonly IServiceProvider _serviceProvider;

        public Speak(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public Speak() : this(StartUp.Container.BuildServiceProvider())
        {
        }

        [LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
        public string Greet(ILambdaContext context)
        {
            var talk = _serviceProvider.GetService<ISpeakService>();

            return talk.Greeting;
        }
    }

```
We need to update our Serverless yaml to take into consideration our refactoring

```js
service: Hello-Configuration

provider:
  name: aws
  runtime: dotnetcore2.1

package:
  individually: true

functions:
  hello:
    handler: HelloConfiguration::Threenine.ConfigTest.Functions.Speak::Greet


    package:
      artifact: bin/release/netcoreapp2.1/hello.zip


```
We will also modify our AppSettings file slightly to create a Greeting section

```js
{
    "greeting" : {
        "message": "This is from the configuration"
    }
}


```
## Build, Deploy and Invoke 

We can now build our lambda

```bash

sudo ./build.sh

```

We can then deploy our Lambda

```bash

sls deploy

```

Then we can invoke it to see if everything works as expected

```bash

sls invoke -f hello

```
### Summary

In this sample, we have enabled our lambda to make use of some great .net core features of Dependency Injection and Configuration. This will enable developers to de-clutter their lambda functions and help to organise their code and also enable the use of additional libraries.