I have previously provided a simple example of how to introduce simple dependency injection and configuration to your Serverless Framework AWS Lambda, 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
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.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.
We will be continuing to develop on the code presented in Simple Dependency Injection In AWS Lambda
Lets generate a new Serverless project
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
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
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 , 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.
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 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 in mind when developing!
So lets add a new class and by convention we'll call this
We are going to slightly refactor our
LambdaConfiguration to make use of
IConfigurationRoot which represents the root of an IConfiguration hierarchy
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
For the sake of demo, I created an additional Directory named Services and created an interface of
ISpeakService and a class called
You'll notice that the
SpeakService with make use of the Options patternprovide a mechanism to validate configuration data . We also seem to using a class called Greeting, lets go ahead and create that class
We can now wire up our dependencies in our StartUp class
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 method to get the service object of the specified type.
We need to update our Serverless yaml to take into consideration our refactoring
We will also modify our AppSettings file slightly to create a Greeting section
Build, Deploy and Invoke
We can now build our lambda
We can then deploy our Lambda
Then we can invoke it to see if everything works as expected
In this sample we have enable 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.