无需编码,自动实现“异步 Request-Reply”模式

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无需编码,自动实现“异步 Request-Reply”模式相关的知识,希望对你有一定的参考价值。

前言

上次,我们虽然用代码实现了“异步 Request-Reply 模式”,但是需要为每一个长时间操作 API 实现一个对应的 AsyncXXX 操作。

其实,可以尝试用 Source Generators 减少这种重复性劳动。

实现思路

  • Controller 类必须是partial,这样才能为它额外增加新方法;

  • 为每个长时间操作 API 声明一个 AsyncMethodAttribute,这样 Source Generators 才知道为谁实现对应的同步操作;

  • 遍历所有声明了 AsyncMethodAttribute 的方法,为其编写实现方法。

具体代码

1.添加 AsyncMethodAttribute

向待编译项目加入 AsyncMethodAttribute 代码:

const string asyncMethodAttributeText = @"using System;

namespace AsyncMethodGenerator

    public sealed class AsyncMethodAttribute : Attribute
    
        public AsyncMethodAttribute()
        
        
    

";

context.AddSource("AsyncMethodAttribute", SourceText.From(asyncMethodAttributeText, Encoding.UTF8));

2.遍历 AsyncMethodAttribute 声明方法

找到声明了 AsyncMethodAttribute 的所有方法:

private string GenerateMethods(SyntaxList<MemberDeclarationSyntax> members)

    StringBuilder stringBuilder = new StringBuilder();

    foreach (var member in members)
    
        if(member is MethodDeclarationSyntax method && HasAsyncMethodAttribute(method))
        
            stringBuilder.Append(GenerateAsyncMethod(method));
        
    
    
    return stringBuilder.ToString();


private bool HasAsyncMethodAttribute(MethodDeclarationSyntax method)

    var hasAttribute = false;
    foreach (var attributeList in method.AttributeLists)
    
        foreach (var attribute in attributeList.Attributes)
        
            if (attribute.Name.ToString().Equals("AsyncMethod"))
            
                hasAttribute = true;
            
        
    

    return hasAttribute;

3.生成 AsyncMethod 代码

根据原方法定义,生成 AsyncMethod 方法:

private string GenerateAsyncMethod(MethodDeclarationSyntax method)

    var stringBuilder = new StringBuilder();

    foreach (var attributeList in method.AttributeLists)
    
        foreach (var attribute in attributeList.Attributes)
        
            if (attribute.Name.ToString().Equals("Route"))
            
                stringBuilder.Append($@"[Route(""async/attribute.ArgumentList.Arguments[0].ToString().Trim('"')"")]");
            
            else
            
                stringBuilder.Append($"[attribute]");
                stringBuilder.Append("\\r\\n");
            
        
    

    stringBuilder.Append($"public async Task<IActionResult> Asyncmethod.Identifier ");
    stringBuilder.Append($"(method.ParameterList.Parameters)");
    stringBuilder.Append("\\r\\n");

    stringBuilder.Append($@"
        
            string id = Guid.NewGuid().ToString();
            string responseValue =  $@""/status/id"";

            _cache.SetString(id, responseValue);

            Task.Factory.StartNew(() =>
            
                var result = GenerateCallingMethod(method).Result;
                _cache.SetString(id + ""_result"", JsonConvert.SerializeObject(result));
            );

            return Accepted(responseValue);
        
    ");

    return stringBuilder.ToString();

4.使用

现在,就可以在目标项目中使用 AsyncMethod 方法了:

[ApiController]
[Route("[controller]")]
public partial class WeatherForecastController : ControllerBase

    ...

    [HttpGet]
    [Route("get")]
    [AsyncMethod]
    public async Task<IEnumerable<WeatherForecast>> Get()
    
        ...
    

注意 WeatherForecastController 是 partial class

结论

有了 Source Generators,可以让编译器帮我们自动实现“异步 Request-Reply 模式”了!

想了解更多内容,请关注我的个人公众号”My IO“

以上是关于无需编码,自动实现“异步 Request-Reply”模式的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch:通过热温冷和冻结层管理数据自动化 — 无需编码!

Elasticsearch:通过热温冷和冻结层管理数据自动化 — 无需编码!

GitHub 近两万 Star,无需编码,可一键生成前后端代码,开源项目

实现CodeFirst自动数据迁移无需命令

有没有办法从多个 URL 生成 Web 查询,而无需在 Excel 中对值进行硬编码?

无需额外过滤即可返回所有带有预输入的远程匹配项