c# - 如何为多个 WCF 客户端创建 Polly 的策略

标签 c# wcf dry polly

我需要集成第 3 方服务。它有 3 个端点,用于 3 个调用。就是这样,每个 API 调用都有自己的端点和自己的 wsdl。因此,不同调用的 POCO 之间没有任何联系(如继承)。但是这些调用的结果非常相似。特别是每个结果都有“错误”属性,其中包含管道分隔字符串中的错误。一些错误在调用之间共享(具有相同的名称)并且必须以类似的方式处理。

我的目标是在引发异常或错误中出现名为“EXCEPTION”的错误时重试调用。我正在尝试使用 Polly 来实现这个目标。我现在看到的唯一方法是为每个调用创建单独的策略。有什么方法可以为所有调用创建单一策略吗?

示例代码如下(在实际项目中*结果类和*服务接口(interface)在导入 wsdl 时由 VisualStudio 自动生成):

public partial class CreateResult
{
    public string Errors {get;set;} 
}

public interface ICreateService
{
    Task<CreateResult> CreateAsync();
}

public partial class UpdateResult
{
    public string Errors {get;set;} 
}

public interface IUpdateService
{
    Task<UpdateResult> UpdateAsync();
}

public partial class DeleteResult
{
    public string Errors {get;set;} 
}

public interface IDeleteService
{
    Task<DeleteResult> DeleteAsync();
}

public class Connector
{
    private readonly ICreateService _createService;
    private readonly IUpdateService _updateService;
    private readonly IDeleteService _deleteService;
    private readonly Policy _policy = ???; 

    public Connector(ICreateService createService, IUpdateService updateService, IDeleteService deleteService)
    {
        _createService = createService;
        _updateService = updateService;
        _deleteService = deleteService;
    }

    public async Task<CreateResult> CreateAsync()
    {
        // sample policy: var policy = Policy.Handle<Exception>()
        //                                   .OrResult<CreateResult>(r => r.Errors.Contains("EXCEPTION"))
        //                                   .Retry();
        // Now I need to create such a policy for every call. How can I create a single policy or a factory method to enforce DRY principle?

        return _policy.ExecuteAsync(() => _createService.CreateAsync());
    }

    public async Task<UpdateAsync> UpdateAsync()
    {
        return _policy.ExecuteAsync(() => _updateService.UpdateAsync());
    }

    public async Task<DeleteResult> DeleteAsync()
    {
        return _policy.ExecuteAsync(() => _deleteService.DeleteAsync());
    }
}

最佳答案

假设每个返回类型都有一个包含 Error 对象集合的属性,您可以通过让每个策略重用检查该集合的方法来消除一些代码重复。

例如:

public static class PolicyExtensions
{
    public static bool ContainsExceptionMessage(this IEnumerable<Error> errors)
    {
        return errors.Any(error => error.Name.Contains("EXCEPTION"));
    }
}

您将需要多个策略,但每个策略都可以重用此方法:

var policy = Policy.HandleResult<MyResultClass>(
    result => result.Errors.ContainsExceptionMessage())
        .Or<Exception>()
        .Retry();

如果您的每个类都实现了一个表明它包含错误集合的接口(interface),您还可以创建一个通用函数来返回一个策略:

public interface IHasErrors
{
    List<Error> Errors { get; }
}

Policy<THasErrors> CreateExceptionPolicy<THasErrors>() where THasErrors:IHasErrors
{
    return Policy.HandleResult<THasErrors>(
            result => result.Errors.ContainsExceptionMessage())
        .Or<Exception>()
        .Retry();
}

现在您仍然在创建多个策略,但它们更容易创建,而且它们的代码都没有重复。

var policy = CreateExceptionPolicy<UpdateResult>();

关于c# - 如何为多个 WCF 客户端创建 Polly 的策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48412675/

相关文章:

c# - 如何在 ASP.NET MVC 中将数据从 View 传递到 UserControl?

asp.net - WCF REST 服务模板 40 和 JSON 格式的 Entity Framework 返回空响应

sql - 如何重用大型查询而不重复它?

.net - 带有 SSL 终止负载平衡服务器的 WCF

cakephp - 需要在cakePHP中输入全名

ruby-on-rails - 保持干燥,但由于不同原因想要重复

c# - 为什么我在这条线上收到错误消息?

c# - 如何传递包含此的类对象并调用该类的方法

C#:自定义数组排序

c# - 如何从 javascript 调用 WCF 服务?