【问题标题】:how to access data structure from web API controller in .NET where the structure needs to be modified by the API controller如何从 .NET 中的 Web API 控制器访问需要由 API 控制器修改结构的数据结构
【发布时间】:2020-11-04 08:22:33
【问题描述】:

在为 .NET 核心 Web API 的 Controller 类旁边创建本地数据结构的最佳做法是什么。

我有一个用 .NET 编写的 Web API,它注入了记录器和 Kafka 生产者:

public LoadTestController(ILogger<LoadTestController> logger,
             IEventBusProducer<string, string> producer)
        {
            _logger = logger;
            _producer = producer;
            _messages = new Dictionary<int, Sample>();
        }

我需要使用字典来确定是否发送了某个大小的先前消息。但是,对于每个 POST 请求,都会再次为 LoadTestController 调用构造函数。

实现这一目标的最佳做法是什么?

最好以某种方式注入该字典(从启动通过引用传递并根据请求进行修改)?还是创建拥有此数据结构的新单点服务?

【问题讨论】:

  • 好吧,最好的做法是单例服务,作为一种存储库
  • @PatrickBeynio 你需要更具体一点。谢谢
  • 我的新答案是否足够具体?
  • @PatrickBeynio 我正在审查您的答案并即将采取这种方法。非常感谢

标签: .net .net-core asp.net-core-webapi


【解决方案1】:

在您的情况下,最佳做法是添加一个单例服务,用作存储库。

Singleton service registration

您可以通过以下任一方式添加单例服务
提供课程

    services.AddSingleton<ISingletonService, SingletonService>();

或实例

    services.AddSingleton<ISingletonService>(new SingletonService());

或委托

    services.AddSingleton<ISingletonService>(sp => new SingletonService());

进入ConfigureServices

public void ConfigureServices(IServiceCollection services)
{
    // other registrations

    services.AddSingleton<ISingletonService, SingletonService>();
    // or
    services.AddSingleton<ISingletonService>(new SingletonService());
    // or
    services.AddSingleton<ISingletonService>(sp => new SingletonService());
}

Design services for dependency injection

最佳做法是:

  • 设计服务以使用依赖注入来获取它们的 依赖关系。
  • 避免有状态的静态类和成员。设计应用程序 改为使用单例服务,从而避免创建全局状态。
  • 避免在服务中直接实例化依赖类。
  • 直接实例化将代码耦合到特定实现。 使应用类更小、设计合理且易于测试。

此外,在您的情况下,您可能希望保护您的 Dictionary 以防止并发请求,如果该服务的使用足够简单,ConcurrentDictionary 可能会为您提供很好的服务。

如果服务充当存储库,它至少应该具有设置和获取数据的方法。否则,您可能会发现存储库模式的更高级示例here

Dependency injection into controllers

您可以通过将服务作为参数添加到构造函数中来简单地注入服务

public class MyController
{
    private readonly ISingletonService _service;

    public MyController(ISingletonService service)
    {
        _service = service;
    }

    public IActionResult About()
    {
        return Content( $"Current value: {_service.Get(111)}");
    }
}

或使用FromServices 属性进入操作

public IActionResult About([FromServices] ISingletonService service)
{
    return Content( $"Current value: {service.Get(111)}");
}

最少的实现

使用最佳实践,您应该为您的实现赋予语义价值,但请记住,通过继承提供功能是完全可以的!
因此,如果您真的只需要 Dictionary 的功能,这是您的最小服务实现,可能如下所示:

public interface IMessageRepository : IDictionary<int, Sample> { }

public class MessageRepository : ConcurrentDictionary<int, Sample>, IMessageRepository { }

【讨论】:

  • 感谢您提供非常详细和有条理的答案:)
猜你喜欢
  • 2013-12-09
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2017-09-24
  • 1970-01-01
  • 1970-01-01
  • 2015-05-04
  • 2019-03-11
相关资源
最近更新 更多