代码之家  ›  专栏  ›  技术社区  ›  Oleg Sh

如何更好地构建体系结构

  •  1
  • Oleg Sh  · 技术社区  · 7 年前

    我有一个ASP.NET核心应用程序,它调用另一个库中的服务。这个 服务与外部API一起工作,这需要 sessionId . 我们必须调用一个登录API方法来获取 会话ID 会话ID 会话ID 可以对1个请求、10个请求、100个请求有效,可以对1分钟、10分钟、1天有效。。。没人知道。

    public class BillRequest
    {
        private readonly HttpClient client;
    
        public BillRequest()
        {
            client = new HttpClient
            {
                BaseAddress = new Uri("https://myapi.com/api/v2/")
            };
        }
    
        public async Task<List<Dto1>> CustomerBankAccountListAsync(int start, int count)
        {
            List<KeyValuePair<string, string>> nvc = new List<KeyValuePair<string, string>>
            {
                new KeyValuePair<string, string>("sessionId", CURRENT_SESSION_ID)
            };
    
            var customerStream = await client.PostAsync("List/CustomerBankAccount.json", new FormUrlEncodedContent(nvc));
            var customerString = await customerStream.Content.ReadAsStringAsync();
            //....
        }
    
        public async Task<List<Dto2>> Method2(int start, int count)
        {
            List<KeyValuePair<string, string>> nvc = new List<KeyValuePair<string, string>>
            {
                new KeyValuePair<string, string>("sessionId", CURRENT_SESSION_ID)
            };
    
            var customerStream = await client.PostAsync("List/Method2.json", new FormUrlEncodedContent(nvc));
            var customerString = await customerStream.Content.ReadAsStringAsync();
            //....
        }
    
        // logic to get SessionId here
        public async Task LoginAsync()
        {
    
        }
    

    如何实现以保存此文件 内部服务?

    1. 呼叫 Login 方法,然后再调用方法。易于实现,但方法不好,因为我们有许多不必要的请求,然后使用

    2. 拯救 会话ID 登录 方法,该方法将返回一个新的 会话ID . 在这种情况下,我们必须通过 会话ID BillRequest 班这是可行的,但我不喜欢将服务的责任转移到其他人身上,因为如何使用API是服务的内部责任。

    3. 拯救 会话ID 在服务本身内部和召回 登录 服务内部的方法(旧时) 会话ID 被认为是无效的,用new等重写它。但是如何在内存中将它保存为“静态”呢?我不想将它保存到任何外部位置(文件系统、云等),但我也不能保存到类的变量,因为类的对象可以重新创建。。。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Zazaeil    7 年前

    我建议在这里向函数式编程转变。

    sessionID 例如 指独立的值,而不是单个对象。然后,您的问题可以通过以下(语义等价)方式重新定义:给定一个类型化流( string 看到 它的流程和 反应 在输入更改时,源代码不控制哪些更改?

    那么,有一个答案,一个企业已经证明了: reactive extensions .

    从技术上来说,这样的转变是最简单的,因为你正在处理一个 IObservable<string> 在控制器内部,可以通过标准的.NET Core DI方法注入,也可以由构造函数简单地定义。这很灵活,因为 rX 也与本机兼容 Task 因此, async/await 特色一个很好的事实是,从外部世界注入所需的行为并用一个更合适的行为来修饰现有的可观察行为是非常容易的:所以,您是安全的:一旦第三方的服务逻辑发生变化,您几乎可以立即、毫不费力地采用您的代码库。

    IObservable<字符串> ? 嗯,我不能说,因为你没有提供足够的信息。这可能是一个错误 interval 询问远程服务器是否当前 会话ID timer 负责编译时已知的过期规则,它可能是您所需要的复杂逻辑: 接收 它足够灵活,只要处理(可能的无限)流,就不会限制您使用它可以实现什么。

    不是 任务 await 如果你想坚持一种普通的.NET时尚的话。