Объединение асинхронных и неасинхронных реализаций для шаблона абстрактной фабрики - PullRequest
0 голосов
/ 08 мая 2018

У нас есть приложение ASP.Net MVC для нашего интернет-магазина. Пользователь должен выбрать один из нескольких способов оплаты, чтобы что-то купить. Для этого мы реализовали абстрактный шаблон фабрики:

public interface IPaymentServiceFactory
{
    IPaymentService GetPaymentService(PaymentServiceEnum paymentServiceType);
}
public interface IPaymentService
{
    PaymentSettingsModel GetPaymentSettingsModel();
}

Используется в нашем действии:

public ActionResult ProcessCart(PaymentDataModel paymentData)
{
    var paymentService = _paymentServiceFactory.GetPaymentService(paymentData.PaymentServiceType);
    var paymentSettings = paymentService.GetPaymentSettingsModel();
}

Проблема возникает, когда мы понимаем, что некоторые способы оплаты требуют асинхронных вызовов внутри. Например, для создания объекта платежа на их стороне должен быть асинхронно вызван метод стороннего сервиса онлайн-платежей через http. Реализация:

    public class OnlinePaymentService : IPaymentService
    {
        private readonly IOnlinePaymentServiceApiClient _client;
        public async Task<PaymentSettingsModel> GetPaymentSettings()
        {
            var result =  await _client.CreatePaymentAsync();
            return result;
        }
    }

Поэтому у нас возникает вопрос: как обрабатывать сценарии асинхронизации и синхронизации для разных способов оплаты. Мы решили сделать все асинхронным. Обновленный код:

public interface IPaymentService
{
    Task<PaymentSettingsModel> GetPaymentSettings();
}
public async Task<ActionResult> ProcessCart(PaymentDataModel paymentData)
{
    var paymentService = _paymentServiceFactory.GetPaymentService(paymentData.PaymentServiceType);
    var paymentSettings = await paymentService.GetPaymentSettingsModel();
}

Пока все хорошо, но для реализации этого для всех других способов оплаты мы были вынуждены использовать Task.Run:

    public class CashPaymentService : IPaymentService
    {
        public async Task<PaymentSettingsModel> GetPaymentSettings()
        {
            return await Task.Run(() => new PaymentSettingsModel());;
        }
    }

Как я понимаю, это создает два разных потока для обработки Action, что может вызвать проблему производительности . Есть ли способ избежать таких последствий? Неужели так плохо использовать Task.Run в конкретном случае?

1 Ответ

0 голосов
/ 08 мая 2018

Неужели так плохо использовать Task.Run в конкретном случае?

Да, главным образом потому, что это излишне усложняет вещи.

Вы можете вернуть завершенное задание, результатом которого является заданное значение, используя Task.FromResult.

Это полностью синхронно:

public class CashPaymentService : IPaymentService
{
    public Task<PaymentSettingsModel> GetPaymentSettings()
    {
        return Task.FromResult( new PaymentSettingsModel() );
    }
}

Обратите внимание, что здесь отсутствует async - это возможно, потому что это деталь реализации, а не часть определения IPaymentService.

...