简体   繁体   English

为抽象工厂模式组合异步和非异步实现

[英]Combine async and not async implementations for the abstract factory pattern

We have an ASP.Net MVC application for our online store. 我们的在线商店有一个ASP.Net MVC应用程序。 User has to choose from multiple payment methods in order to buy something. 用户必须从多种付款方式中进行选择才能购买商品。 For this we have implemented an abstract factory pattern: 为此,我们实现了一个抽象的工厂模式:

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

It is used in our Action: 它在我们的动作中使用:

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

The problem occurs when we understand that some payment methods require async calls inside. 当我们了解到某些付款方式需要在内部进行异步调用时,就会出现问题。 For example 3rd party online payment service method must be asynchronously called through http for creating payment object on their side. 例如,必须通过http异步调用第三方在线支付服务方法,以在其一侧创建支付对象。 The implemetation: 实现:

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

So we come up with a question: How to handle async and sync scenario for different payment methods. 因此,我们提出一个问题:如何处理不同付款方式的异步和同步方案。 We`v decided to make everything async. 我们决定让一切都异步。 Updated code: 更新的代码:

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

So far so good, but for implementing this for all other payment methods we were forced to use Task.Run: 到目前为止,一切都很好,但是为了将其用于所有其他付款方式,我们被迫使用Task.Run:

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

As i can understand this creates two different threads for processing Action, which can cause performance issue . 据我了解,这会创建两个不同的线程来处理Action,这可能会导致性能问题 Is there way to avoid such consequences? 有办法避免这种后果吗? Is it really so bad to use Task.Run in particular case? 在特定情况下使用Task.Run真的很糟糕吗?

Is it really so bad to use Task.Run in particular case? 在特定情况下使用Task.Run真的很糟糕吗?

Yes, mainly because it's unnecessarily complicating things. 是的,主要是因为它不必要地使事情复杂化。

You can return a completed task whose result is a given value using Task.FromResult . 您可以使用Task.FromResult返回结果为给定值的已完成任务。

This is completely synchronous: 这是完全同步的:

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

Note that async is missing here - that's possible because it is an implementation detail and not part of the definition of IPaymentService . 请注意,这里缺少async ,这是可能的,因为它是实现细节,而不是IPaymentService定义的一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM