Должен ли я создавать и повторно использовать AmazonSimpleEmailServiceClient как синглтон?

Документы SES для .NET показывает отправку электронной почты с использованием AmazonSimpleEmailServiceClient, инициализированного оператором using:

using (var client = new AmazonSimpleEmailServiceClient(RegionEndpoint.USWest2))
{
    //...
}

Я понимаю, что это нормально для примера, однако в моем рабочем приложении я должен инициализировать AmazonSimpleEmailServiceClient только один раз, а затем повторно использовать его?

// MailSender is registered with DI as Singleton
public class MailSender
{
    private AmazonSimpleEmailServiceClient _client;

    public MailSender()
    {
        _client = new AmazonSimpleEmailServiceClient(RegionEndpoint.USWest2);
    }

    public void SendEmail()
    {
        // ...
        _client.SendEmail(request);
    }
}

Мое производственное приложение отправляет большое количество электронных писем. Я не уверен, как ведет себя объект AmazonSimpleEmailServiceClient, но было бы более эффективно создать один экземпляр, а не обновлять его каждый раз, когда отправляется электронное письмо.

Это IDisposable. IDisposableпровоцирует разработчик, который утилизирует экземпляр. Удаление синглтона может привести к сбоям в некоторых частях вашего приложения. Зачем вам нужен синглтон?

Kyle 13.03.2019 18:11

Возможный дубликат Должен ли я реализовать IDisposable на синглтоне?

Kyle 13.03.2019 18:14

Мое производственное приложение отправляет большое количество электронных писем. Я не уверен, как ведет себя объект AmazonSimpleEmailServiceClient, но было бы более эффективно создать один экземпляр, а не обновлять его каждый раз, когда отправляется электронное письмо.

kspearrin 13.03.2019 18:14

Я бы посоветовал против Синглтона, хотя. Всегда есть способы перестроить вашу логику таким образом, чтобы вы рассылали электронные письма пакетами. Например: using(var emailer) { foreach(var email) { emailer.Send(email) } }

Kyle 13.03.2019 18:17
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
544
2

Ответы 2

Да, вы всегда должны создавать экземпляры классов, которые собираетесь использовать более одного раза. В языке, отличном от GarbageCollector (например, C++), создание экземпляров классов везде может быть проблемой, а не их удаление.

При повторном использовании класса вы заботитесь не только о производительности, но и о параллелизме.

При этом беглый взгляд на исходный код показывает, что этот класс вызывает метод AmazonWebServiceClient базового класса Dispose:

#region Dispose

protected override void Dispose(bool disposing)
{
    base.Dispose(disposing);
}
#endregion

Базовый класс не переопределяет метод Dispose и вместо этого полагается на собственный базовый класс AbstractWebServiceClient:

/// <summary>
/// Implements the Dispose pattern for the AmazonWebServiceClient
/// </summary>
/// <param name = "disposing">Whether this object is being disposed via a call to Dispose
/// or garbage collected.</param>
protected virtual void Dispose(bool disposing)
{
    if (!this.disposed)
    {
        if (disposing && logger != null)
        {
            logger.Flush();
            logger = null;
        }
        this.disposed = true;
    }
}

Обратите внимание, что метод Dispose очищает внутренний экземпляр регистратора.

Так что с точки зрения производительности, безусловно, есть что выиграть. Однако, что касается параллелизма, в комментариях к коду нет упоминания о том, что класс является потокобезопасным.

Однако их клиентская документация в жизненных циклах упоминает безопасность потоков и повторное использование классов:

The best-known aspect of the AWS SDK for .NET are the various service clients that you can use to interact with AWS. Client objects are thread safe, disposable, and can be reused. (Client objects are inexpensive, so you are not incurring a large overhead by constructing multiple instances, but it’s not a bad idea to create and reuse a client.)

Надеюсь, это поможет.

Другие вопросы по теме