Introducing .NET Annotations Lambda Framework (Preview)

海外精选
海外精选的内容汇集了全球优质的亚马逊云科技相关技术内容。同时,内容中提到的“AWS” 是 “Amazon Web Services” 的缩写,在此网站不作为商标展示。
0
0
{"value":"Recently we [released](https://aws.amazon.com/blogs/compute/introducing-the-net-6-runtime-for-aws-lambda/) the .NET 6 managed runtime for Lambda. Along with the new Lambda runtime we have also been working on a new framework for writing .NET 6 Lambda functions called Lambda Annotations. The Annotations framework makes the experience of writing Lambda feel more natural in C#. It also takes care of synchronizing the Lambda functions implemented in your code with your project’s CloudFormation template. This means you don’t have to worry about function handler strings not being set correctly in CloudFormation templates or lose focus while coding to also update your CloudFormation template.\n\nOur goal with the Annotations framework is to be able to take a Lambda function, like the one shown below that uses the regular Lambda program model (which is also defined in a CloudFormation template):\n\nC#\n```\npublic APIGatewayHttpApiV2ProxyResponse LambdaMathAdd(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context)\n{\n if (!request.PathParameters.TryGetValue(\"x\", out var xs))\n {\n return new APIGatewayHttpApiV2ProxyResponse\n {\n StatusCode = (int)HttpStatusCode.BadRequest\n };\n }\n if (!request.PathParameters.TryGetValue(\"y\", out var ys))\n {\n return new APIGatewayHttpApiV2ProxyResponse\n {\n StatusCode = (int)HttpStatusCode.BadRequest\n };\n }\n var x = int.Parse(xs);\n var y = int.Parse(ys);\n return new APIGatewayHttpApiV2ProxyResponse\n {\n StatusCode = (int)HttpStatusCode.OK,\n Body = (x + y).ToString(),\n Headers = new Dictionary<string, string> { { \"Content-Type\", \"text/plain\" } }\n };\n}\n```\n\nand replace it with the simpler version below, removing the typical Lambda function code so you can focus on just the business logic, with a couple of .NET attributes annotating the code:\n\nC#\n```\n[LambdaFunction]\n[HttpApi(LambdaHttpMethod.Get, \"/add/{x}/{y}\")]\npublic int Add(int x, int y)\n{\n return x + y;\n}\n```\n#### **How does Annotations work?**\nThe Lambda programming model is to write a function that takes in at most 2 parameters. The first parameter is an object representing the event triggering the Lambda function. The second parameter is an instance of ILambdaContext which provides information and logging APIs for the running environment. This is what you can see in the first example above, and this programming model hasn’t changed with the introduction of the Annotations framework.\n\nThe second example doesn’t follow the Lambda programming model since it is taking multiple parameters that aren’t the event object. Instead, it is taking in parameters that map to the calling REST API’s resource path. The Annotations framework uses a C# feature called [source generators](https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview) to generate code that translates from the Lambda programming model to what we see in the second example.\n\nAt a high level, here’s what happens when the C# compiler is invoked to build the project: the Annotations framework finds the .NET Lambda attributes indicating Lambda functions and generates new code into the build that handles all of the translation. It also updates the CloudFormation template for the Lambda function, to set the Lambda function handler string to the generated code. For the Annotations example above the function handler string gets set to ```AnnotationsExample::AnnotationsExample.Functions_Add_Generated::Add``` referencing a generating class called ```Functions_Add_Generated```.\n\nA major benefit of using C# source generators to create the translation layer at compile time is that we avoid reflection code at runtime. Since the Annotations framework is doing all the work at compile time and only generating the code that is required for the specific Lambda function, it has minimal impact to Lambda cold start performance. However, source generators are only available for C# which means that, unfortunately, the Annotations framework cannot be used for Lambda functions written using F#.\n\n#### **Getting started**\nThe easiest way to get started with the new framework is using the [AWS Toolkit for Visual Studio 2022](https://marketplace.visualstudio.com/items?itemName=AmazonWebServices.AWSToolkitforVisualStudio2022). Start by creating a project in Visual Studio using the **AWS Serverless Application **project template. The **AWS Serverless Application** project template is used for writing one or more Lambda functions and deploying them to AWS using [AWS CloudFormation](https://aws.amazon.com/cloudformation/), along with any other required AWS resources, as a single unit of deployment.\n\nThe **AWS Serverless Application** project template will launch the Lambda blueprint selection wizard. The wizard has a new option called **Annotations Framework** that uses the new framework.\n\n![image.png](https://dev-media.amazoncloud.cn/2fc99fdaf6ed482a8b6546e3d193ab11_image.png)\n\nAfter you create the project, the project file will have a dependency on the** Amazon.Lambda.Annotations** NuGet package. This package contains the .NET attributes used to annotate the code for Lambda, and the C# source generator that will create the generated translation code.\n\nThe project has a **Function.cs** file containing the Lambda functions, and a **serverless.template** file which is the project’s CloudFormation template where the Lambda functions are defined. Below is a trimmed-down version of the Lambda functions defined in the Function.cs file. For example purposes, the Lambda functions implement a REST API calculator with add, substract, multiply, and divide operations.\n\nC#\n```\n[LambdaFunction()]\n[HttpApi(LambdaHttpMethod.Get, \"/add/{x}/{y}\")]\npublic int Add(int x, int y, ILambdaContext context)\n{\n context.Logger.LogInformation($\"{x} plus {y} is {x + y}\");\n return x + y;\n}\n\n\n[LambdaFunction()]\n[HttpApi(LambdaHttpMethod.Get, \"/substract/{x}/{y}\")]\npublic int Substract(int x, int y, ILambdaContext context)\n{\n context.Logger.LogInformation($\"{x} substract {y} is {x - y}\");\n return x - y;\n}\n\n\n[LambdaFunction()]\n[HttpApi(LambdaHttpMethod.Get, \"/multiply/{x}/{y}\")]\npublic int Multiply(int x, int y, ILambdaContext context)\n{\n context.Logger.LogInformation($\"{x} multiply {y} is {x * y}\");\n return x * y;\n}\n\n\n[LambdaFunction()]\n[HttpApi(LambdaHttpMethod.Get, \"/divide/{x}/{y}\")]\npublic int Divide(int x, int y, ILambdaContext context)\n{\n context.Logger.LogInformation($\"{x} divide {y} is {x / y}\");\n return x / y;\n}\n```\nThe CloudFormation project also has all the Lambda functions defined in it so I can deploy all of these Lambda functions together as a CloudFormation stack.\n\n![image.png](https://dev-media.amazoncloud.cn/7533d088035c4a4489443b9b1f8e3ca0_image.png)\n\n#### **Extending the sample**\nLet’s extend this example by adding the mod (return the remainder of a whole number division) operator. Add the following code in your Function.cs file:\n\nC#\n```\n[LambdaFunction(Timeout = 3, MemorySize = 128)]\n[HttpApi(LambdaHttpMethod.Get, \"/mod/{x}/{y}\")]\npublic int Mod(int x, int y, ILambdaContext context)\n{\n context.Logger.LogInformation($\"{x} mod {y} is {x % y}\");\n return x % y;\n}\n```\nIn this example I set the ```Timeout``` and ```MemorySize``` CloudFormation properties in the ```LambdaFunction``` attribute. The ```HttpApi``` attribute tells the source generator to configure the event source for the function to an API Gateway HTTP API. Additionally the HTTP method is configured as a HTTP ```GET``` with a resource path ```/mod/{x}/{y}```. After the project is compiled the CloudFormation template is automatically updated with the new Lambda function:\n\n![image.png](https://dev-media.amazoncloud.cn/03e637dd15c446fcbe3f09c62c5406eb_image.png)\n\nConfiguring CloudFormation properties for the functions using the .NET attributes is optional. If you prefer you can continue to configure the additional settings in the CloudFormation template.\n\nIn Visual Studio you can deploy the the Lambda functions by right clicking on the project and selecting **Publish to AWS Lambda.**\n\n![image.png](https://dev-media.amazoncloud.cn/358d01cdd63d4104821239ffa3f78ef8_image.png)\n\nBecause the source generator used by the Annotations framework is integrated into the C# compiler, any existing tool chain used for deploying .NET Lambda functions through CloudFormation can deploy Lambda functions using the Annotations framework. Be sure to build the .NET project before deploying to ensure the CloudFormation template is up-to-date.\n\n#### **Configuring dependency injection**\nDependency injection has become commonplace in .NET applications. .NET has its own built-in dependency injection framework available in the Microsoft.Extensions.DependencyInjection NuGet package. The Annotations framework makes it easy to configure dependency injection for Lambda functions using the ```LambdaStartup``` attribute.\n\nIn the project created in the previous section the project template created a class called Startup that has the LambdaStartup attribute applied to it:\n\nC#\n```\n[Amazon.Lambda.Annotations.LambdaStartup]\npublic class Startup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n }\n}\n```\nIn the ```ConfigureServices``` method you can register the services your application needs. For example, AWS service clients from the AWS SDK for .NET and Entity Framework Core context objects.\n\nTo demonstrate how dependency injection works with this framework, lets add an ```ICalculatorService``` service to handle the logic for our Lambda functions. Start by creating a ```CalculatorService.cs``` file containing the following code\n\nC#\n```\npublic interface ICalculatorService\n{\n int Add(int x, int y);\n int Substract(int x, int y);\n int Multiply(int x, int y);\n int Divide(int x, int y);\n}\n\npublic class CalculatorService : ICalculatorService\n{\n public int Add(int x, int y) => x + y;\n\n public int Substract(int x, int y) => x - y;\n\n public int Multiply(int x, int y) => x * y;\n\n public int \n\nDivide(int x, int y) => x / y;\n}\n```\nNow that we have our service we can register it in the ```ConfigureServices``` method in the Startup class. For the calculator service no state is being preserved so we’ll register the service as a singleton. If you want a separate instance of the service per Lambda invocation use the ```AddTransit``` or ```AddScope``` operations.\n\nC#\n```\n[Amazon.Lambda.Annotations.LambdaStartup]\npublic class Startup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddSingleton<ICalculatorService, CalculatorService>(); \n }\n}\n```\n#### **Injecting the services**\nThere are 2 ways to inject services into Lambda function. The first and most common is constructor injection. The constructor for the containing type of the Lambda function takes in the required services. The services can be saved to class fields and used inside the Lambda functions, shown below.\n\nC#\n```\npublic class Functions\n{\n private ICalculatorService _calculatorService;\n\n public Functions(ICalculatorService calculatorService)\n {\n this._calculatorService = calculatorService;\n }\n \n [LambdaFunction()]\n [HttpApi(LambdaHttpMethod.Get, \"/add/{x}/{y}\")]\n public int Add(int x, int y, ILambdaContext context)\n {\n context.Logger.LogInformation($\"{x} plus {y} is {x + y}\");\n return _calculatorService.Add(x, y);\n }\n \n ...\n}\n```\nThis approach works best when using services that were registered as a singleton in the dependency injection container. That is because the instances of the class containing Lambda functions is only constructing once per Lambda compute environment.\n\nIf you have services that need to be recreated for each Lambda invocation then the ```FromServices``` attribute can be used, passing the service in the Lambda function’s list of parameters. The Annotations framework will create a new [dependency inject scope](https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection#constructor-injection-behavior) for each Lambda invocation. So services registered with the ```AddScope``` operation will be created once per invocation. This approach is shown below.\n\nC#\n```\npublic class Functions\n{\n [LambdaFunction()]\n [HttpApi(LambdaHttpMethod.Get, \"/add/{x}/{y}\")]\n public int Add([FromServices] ICalculatorService calculatorService, int x, int y, ILambdaContext context)\n {\n context.Logger.LogInformation($\"{x} plus {y} is {x + y}\");\n return calculatorService.Add(x, y);\n }\n \n ...\n}\n```\n#### **Conclusion**\nThe .NET Lambda Annotations framework is currently in preview, and development of the framework is being done in the [aws/aws-lambda-dotnet](https://github.com/aws/aws-lambda-dotnet) GitHub repository. We have a pinned [GitHub issue](https://github.com/aws/aws-lambda-dotnet/issues/979) where we have been posting updates and it also contains a link to our design doc for the framework. The [README](https://github.com/aws/aws-lambda-dotnet/tree/master/Libraries/src/Amazon.Lambda.Annotations) for the Annotations framework has the list of currently implemented attributes, including ```FromHeader```, ```FromBody```, and ```FromQuery```.\n\nCurrently, the library is focused on Lambda functions for REST APIs. You can also write Lambda functions with just the ```LambdaFunction``` attribute to take advantage of the dependency injection integration and CloudFormation synchronization. We would like to expand the Annotation framework to simplify other event sources like S3 and DynamoDB events, and would love to hear the community’s thoughts on what the best experience would be.\n\nTry out the new Annotations framework and let us know your thoughts on GitHub. It is easy to get started with the new Annotations framework in Visual Studio 2022 using the AWS Toolkit for Visual Studio or the .NET CLI by installing the [Amazon.Lambda.Templates](https://www.nuget.org/packages/Amazon.Lambda.Templates/) NuGet package.","render":"<p>Recently we <a href=\"https://aws.amazon.com/blogs/compute/introducing-the-net-6-runtime-for-aws-lambda/\" target=\"_blank\">released</a> the .NET 6 managed runtime for Lambda. Along with the new Lambda runtime we have also been working on a new framework for writing .NET 6 Lambda functions called Lambda Annotations. The Annotations framework makes the experience of writing Lambda feel more natural in C#. It also takes care of synchronizing the Lambda functions implemented in your code with your project’s CloudFormation template. This means you don’t have to worry about function handler strings not being set correctly in CloudFormation templates or lose focus while coding to also update your CloudFormation template.</p>\n<p>Our goal with the Annotations framework is to be able to take a Lambda function, like the one shown below that uses the regular Lambda program model (which is also defined in a CloudFormation template):</p>\n<p>C#</p>\n<pre><code class=\"lang-\">public APIGatewayHttpApiV2ProxyResponse LambdaMathAdd(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context)\n{\n if (!request.PathParameters.TryGetValue(&quot;x&quot;, out var xs))\n {\n return new APIGatewayHttpApiV2ProxyResponse\n {\n StatusCode = (int)HttpStatusCode.BadRequest\n };\n }\n if (!request.PathParameters.TryGetValue(&quot;y&quot;, out var ys))\n {\n return new APIGatewayHttpApiV2ProxyResponse\n {\n StatusCode = (int)HttpStatusCode.BadRequest\n };\n }\n var x = int.Parse(xs);\n var y = int.Parse(ys);\n return new APIGatewayHttpApiV2ProxyResponse\n {\n StatusCode = (int)HttpStatusCode.OK,\n Body = (x + y).ToString(),\n Headers = new Dictionary&lt;string, string&gt; { { &quot;Content-Type&quot;, &quot;text/plain&quot; } }\n };\n}\n</code></pre>\n<p>and replace it with the simpler version below, removing the typical Lambda function code so you can focus on just the business logic, with a couple of .NET attributes annotating the code:</p>\n<p>C#</p>\n<pre><code class=\"lang-\">[LambdaFunction]\n[HttpApi(LambdaHttpMethod.Get, &quot;/add/{x}/{y}&quot;)]\npublic int Add(int x, int y)\n{\n return x + y;\n}\n</code></pre>\n<h4><a id=\"How_does_Annotations_work_44\"></a><strong>How does Annotations work?</strong></h4>\n<p>The Lambda programming model is to write a function that takes in at most 2 parameters. The first parameter is an object representing the event triggering the Lambda function. The second parameter is an instance of ILambdaContext which provides information and logging APIs for the running environment. This is what you can see in the first example above, and this programming model hasn’t changed with the introduction of the Annotations framework.</p>\n<p>The second example doesn’t follow the Lambda programming model since it is taking multiple parameters that aren’t the event object. Instead, it is taking in parameters that map to the calling REST API’s resource path. The Annotations framework uses a C# feature called <a href=\"https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview\" target=\"_blank\">source generators</a> to generate code that translates from the Lambda programming model to what we see in the second example.</p>\n<p>At a high level, here’s what happens when the C# compiler is invoked to build the project: the Annotations framework finds the .NET Lambda attributes indicating Lambda functions and generates new code into the build that handles all of the translation. It also updates the CloudFormation template for the Lambda function, to set the Lambda function handler string to the generated code. For the Annotations example above the function handler string gets set to <code>AnnotationsExample::AnnotationsExample.Functions_Add_Generated::Add</code> referencing a generating class called <code>Functions_Add_Generated</code>.</p>\n<p>A major benefit of using C# source generators to create the translation layer at compile time is that we avoid reflection code at runtime. Since the Annotations framework is doing all the work at compile time and only generating the code that is required for the specific Lambda function, it has minimal impact to Lambda cold start performance. However, source generators are only available for C# which means that, unfortunately, the Annotations framework cannot be used for Lambda functions written using F#.</p>\n<h4><a id=\"Getting_started_53\"></a><strong>Getting started</strong></h4>\n<p>The easiest way to get started with the new framework is using the <a href=\"https://marketplace.visualstudio.com/items?itemName=AmazonWebServices.AWSToolkitforVisualStudio2022\" target=\"_blank\">AWS Toolkit for Visual Studio 2022</a>. Start by creating a project in Visual Studio using the **AWS Serverless Application **project template. The <strong>AWS Serverless Application</strong> project template is used for writing one or more Lambda functions and deploying them to AWS using <a href=\"https://aws.amazon.com/cloudformation/\" target=\"_blank\">AWS CloudFormation</a>, along with any other required AWS resources, as a single unit of deployment.</p>\n<p>The <strong>AWS Serverless Application</strong> project template will launch the Lambda blueprint selection wizard. The wizard has a new option called <strong>Annotations Framework</strong> that uses the new framework.</p>\n<p><img src=\"https://dev-media.amazoncloud.cn/2fc99fdaf6ed482a8b6546e3d193ab11_image.png\" alt=\"image.png\" /></p>\n<p>After you create the project, the project file will have a dependency on the** Amazon.Lambda.Annotations** NuGet package. This package contains the .NET attributes used to annotate the code for Lambda, and the C# source generator that will create the generated translation code.</p>\n<p>The project has a <strong>Function.cs</strong> file containing the Lambda functions, and a <strong>serverless.template</strong> file which is the project’s CloudFormation template where the Lambda functions are defined. Below is a trimmed-down version of the Lambda functions defined in the Function.cs file. For example purposes, the Lambda functions implement a REST API calculator with add, substract, multiply, and divide operations.</p>\n<p>C#</p>\n<pre><code class=\"lang-\">[LambdaFunction()]\n[HttpApi(LambdaHttpMethod.Get, &quot;/add/{x}/{y}&quot;)]\npublic int Add(int x, int y, ILambdaContext context)\n{\n context.Logger.LogInformation($&quot;{x} plus {y} is {x + y}&quot;);\n return x + y;\n}\n\n\n[LambdaFunction()]\n[HttpApi(LambdaHttpMethod.Get, &quot;/substract/{x}/{y}&quot;)]\npublic int Substract(int x, int y, ILambdaContext context)\n{\n context.Logger.LogInformation($&quot;{x} substract {y} is {x - y}&quot;);\n return x - y;\n}\n\n\n[LambdaFunction()]\n[HttpApi(LambdaHttpMethod.Get, &quot;/multiply/{x}/{y}&quot;)]\npublic int Multiply(int x, int y, ILambdaContext context)\n{\n context.Logger.LogInformation($&quot;{x} multiply {y} is {x * y}&quot;);\n return x * y;\n}\n\n\n[LambdaFunction()]\n[HttpApi(LambdaHttpMethod.Get, &quot;/divide/{x}/{y}&quot;)]\npublic int Divide(int x, int y, ILambdaContext context)\n{\n context.Logger.LogInformation($&quot;{x} divide {y} is {x / y}&quot;);\n return x / y;\n}\n</code></pre>\n<p>The CloudFormation project also has all the Lambda functions defined in it so I can deploy all of these Lambda functions together as a CloudFormation stack.</p>\n<p><img src=\"https://dev-media.amazoncloud.cn/7533d088035c4a4489443b9b1f8e3ca0_image.png\" alt=\"image.png\" /></p>\n<h4><a id=\"Extending_the_sample_105\"></a><strong>Extending the sample</strong></h4>\n<p>Let’s extend this example by adding the mod (return the remainder of a whole number division) operator. Add the following code in your Function.cs file:</p>\n<p>C#</p>\n<pre><code class=\"lang-\">[LambdaFunction(Timeout = 3, MemorySize = 128)]\n[HttpApi(LambdaHttpMethod.Get, &quot;/mod/{x}/{y}&quot;)]\npublic int Mod(int x, int y, ILambdaContext context)\n{\n context.Logger.LogInformation($&quot;{x} mod {y} is {x % y}&quot;);\n return x % y;\n}\n</code></pre>\n<p>In this example I set the <code>Timeout</code> and <code>MemorySize</code> CloudFormation properties in the <code>LambdaFunction</code> attribute. The <code>HttpApi</code> attribute tells the source generator to configure the event source for the function to an API Gateway HTTP API. Additionally the HTTP method is configured as a HTTP <code>GET</code> with a resource path <code>/mod/{x}/{y}</code>. After the project is compiled the CloudFormation template is automatically updated with the new Lambda function:</p>\n<p><img src=\"https://dev-media.amazoncloud.cn/03e637dd15c446fcbe3f09c62c5406eb_image.png\" alt=\"image.png\" /></p>\n<p>Configuring CloudFormation properties for the functions using the .NET attributes is optional. If you prefer you can continue to configure the additional settings in the CloudFormation template.</p>\n<p>In Visual Studio you can deploy the the Lambda functions by right clicking on the project and selecting <strong>Publish to AWS Lambda.</strong></p>\n<p><img src=\"https://dev-media.amazoncloud.cn/358d01cdd63d4104821239ffa3f78ef8_image.png\" alt=\"image.png\" /></p>\n<p>Because the source generator used by the Annotations framework is integrated into the C# compiler, any existing tool chain used for deploying .NET Lambda functions through CloudFormation can deploy Lambda functions using the Annotations framework. Be sure to build the .NET project before deploying to ensure the CloudFormation template is up-to-date.</p>\n<h4><a id=\"Configuring_dependency_injection_130\"></a><strong>Configuring dependency injection</strong></h4>\n<p>Dependency injection has become commonplace in .NET applications. .NET has its own built-in dependency injection framework available in the Microsoft.Extensions.DependencyInjection NuGet package. The Annotations framework makes it easy to configure dependency injection for Lambda functions using the <code>LambdaStartup</code> attribute.</p>\n<p>In the project created in the previous section the project template created a class called Startup that has the LambdaStartup attribute applied to it:</p>\n<p>C#</p>\n<pre><code class=\"lang-\">[Amazon.Lambda.Annotations.LambdaStartup]\npublic class Startup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n }\n}\n</code></pre>\n<p>In the <code>ConfigureServices</code> method you can register the services your application needs. For example, AWS service clients from the AWS SDK for .NET and Entity Framework Core context objects.</p>\n<p>To demonstrate how dependency injection works with this framework, lets add an <code>ICalculatorService</code> service to handle the logic for our Lambda functions. Start by creating a <code>CalculatorService.cs</code> file containing the following code</p>\n<p>C#</p>\n<pre><code class=\"lang-\">public interface ICalculatorService\n{\n int Add(int x, int y);\n int Substract(int x, int y);\n int Multiply(int x, int y);\n int Divide(int x, int y);\n}\n\npublic class CalculatorService : ICalculatorService\n{\n public int Add(int x, int y) =&gt; x + y;\n\n public int Substract(int x, int y) =&gt; x - y;\n\n public int Multiply(int x, int y) =&gt; x * y;\n\n public int \n\nDivide(int x, int y) =&gt; x / y;\n}\n</code></pre>\n<p>Now that we have our service we can register it in the <code>ConfigureServices</code> method in the Startup class. For the calculator service no state is being preserved so we’ll register the service as a singleton. If you want a separate instance of the service per Lambda invocation use the <code>AddTransit</code> or <code>AddScope</code> operations.</p>\n<p>C#</p>\n<pre><code class=\"lang-\">[Amazon.Lambda.Annotations.LambdaStartup]\npublic class Startup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddSingleton&lt;ICalculatorService, CalculatorService&gt;(); \n }\n}\n</code></pre>\n<h4><a id=\"Injecting_the_services_185\"></a><strong>Injecting the services</strong></h4>\n<p>There are 2 ways to inject services into Lambda function. The first and most common is constructor injection. The constructor for the containing type of the Lambda function takes in the required services. The services can be saved to class fields and used inside the Lambda functions, shown below.</p>\n<p>C#</p>\n<pre><code class=\"lang-\">public class Functions\n{\n private ICalculatorService _calculatorService;\n\n public Functions(ICalculatorService calculatorService)\n {\n this._calculatorService = calculatorService;\n }\n \n [LambdaFunction()]\n [HttpApi(LambdaHttpMethod.Get, &quot;/add/{x}/{y}&quot;)]\n public int Add(int x, int y, ILambdaContext context)\n {\n context.Logger.LogInformation($&quot;{x} plus {y} is {x + y}&quot;);\n return _calculatorService.Add(x, y);\n }\n \n ...\n}\n</code></pre>\n<p>This approach works best when using services that were registered as a singleton in the dependency injection container. That is because the instances of the class containing Lambda functions is only constructing once per Lambda compute environment.</p>\n<p>If you have services that need to be recreated for each Lambda invocation then the <code>FromServices</code> attribute can be used, passing the service in the Lambda function’s list of parameters. The Annotations framework will create a new <a href=\"https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection#constructor-injection-behavior\" target=\"_blank\">dependency inject scope</a> for each Lambda invocation. So services registered with the <code>AddScope</code> operation will be created once per invocation. This approach is shown below.</p>\n<p>C#</p>\n<pre><code class=\"lang-\">public class Functions\n{\n [LambdaFunction()]\n [HttpApi(LambdaHttpMethod.Get, &quot;/add/{x}/{y}&quot;)]\n public int Add([FromServices] ICalculatorService calculatorService, int x, int y, ILambdaContext context)\n {\n context.Logger.LogInformation($&quot;{x} plus {y} is {x + y}&quot;);\n return calculatorService.Add(x, y);\n }\n \n ...\n}\n</code></pre>\n<h4><a id=\"Conclusion_229\"></a><strong>Conclusion</strong></h4>\n<p>The .NET Lambda Annotations framework is currently in preview, and development of the framework is being done in the <a href=\"https://github.com/aws/aws-lambda-dotnet\" target=\"_blank\">aws/aws-lambda-dotnet</a> GitHub repository. We have a pinned <a href=\"https://github.com/aws/aws-lambda-dotnet/issues/979\" target=\"_blank\">GitHub issue</a> where we have been posting updates and it also contains a link to our design doc for the framework. The <a href=\"https://github.com/aws/aws-lambda-dotnet/tree/master/Libraries/src/Amazon.Lambda.Annotations\" target=\"_blank\">README</a> for the Annotations framework has the list of currently implemented attributes, including <code>FromHeader</code>, <code>FromBody</code>, and <code>FromQuery</code>.</p>\n<p>Currently, the library is focused on Lambda functions for REST APIs. You can also write Lambda functions with just the <code>LambdaFunction</code> attribute to take advantage of the dependency injection integration and CloudFormation synchronization. We would like to expand the Annotation framework to simplify other event sources like S3 and DynamoDB events, and would love to hear the community’s thoughts on what the best experience would be.</p>\n<p>Try out the new Annotations framework and let us know your thoughts on GitHub. It is easy to get started with the new Annotations framework in Visual Studio 2022 using the AWS Toolkit for Visual Studio or the .NET CLI by installing the <a href=\"https://www.nuget.org/packages/Amazon.Lambda.Templates/\" target=\"_blank\">Amazon.Lambda.Templates</a> NuGet package.</p>\n"}
目录
亚马逊云科技解决方案 基于行业客户应用场景及技术领域的解决方案
联系亚马逊云科技专家
亚马逊云科技解决方案
基于行业客户应用场景及技术领域的解决方案
联系专家
0
目录
关闭
contact-us