我正在尝试将Specification pattern应用于我的验证逻辑。但是我在异步验证方面遇到了一些问题。
假设我有一个需要验证的实体AddRequest(具有2个字符串属性FileName和Content)。
我需要创建3个验证器:

  • 验证FileName是否不包含无效字符
  • 验证内容是否正确
  • 异步验证数据库中是否存在带有FileName的文件。在这种情况下,我应该有类似Task<bool> IsSatisfiedByAsync的内容

  • 但是,如何同时实现IsSatisfiedByIsSatisfiedByAsync呢?我应该创建2个像ISpecificationIAsyncSpecification的界面,还是可以合而为一?
    我的ISpecification版本(我只需要And)
        public interface ISpecification
        {
            bool IsSatisfiedBy(object candidate);
            ISpecification And(ISpecification other);
        }
    
    和规范
    public class AndSpecification : CompositeSpecification
    {
        private ISpecification leftCondition;
        private ISpecification rightCondition;
    
        public AndSpecification(ISpecification left, ISpecification right)
        {
            leftCondition = left;
            rightCondition = right;
        }
    
        public override bool IsSatisfiedBy(object o)
        {
            return leftCondition.IsSatisfiedBy(o) && rightCondition.IsSatisfiedBy(o);
        }
    }
    
    要验证文件是否存在,我应该使用:
     await _fileStorage.FileExistsAsync(addRequest.FileName);
    
    如果确实需要异步,该如何为该检查编写IsSatisfiedBy
    例如,这里我的FileName验证器(1)
    public class FileNameSpecification : CompositeSpecification
    {
        private static readonly char[] _invalidEndingCharacters = { '.', '/' };
    
        public override bool IsSatisfiedBy(object o)
        {
            var request = (AddRequest)o;
            if (string.IsNullOrEmpty(request.FileName))
            {
                return false;
            }
            if (request.FileName.Length > 1024)
            {
                return false;
            }
            if (request.FileName.Contains('\\') || _invalidEndingCharacters.Contains(request.FileName.Last()))
            {
                return false;
            }
    
            return true
        }
    }
    
    我需要创建FileExistsSpecification并像这样使用:
    var validations = new FileNameSpecification().And(new FileExistsSpecification());
    if(validations.IsSatisfiedBy(addRequest))
    { ... }
    
    但是,如果需要异步该如何创建FileExistsSpecification

    最佳答案



    您可以定义同步和异步接口(interface),但是任何通用的复合实现都必须仅实现异步版本。

    由于asynchronous methods on interfaces mean "this might be asynchronous"而同步方法意味着“这必须是同步的”,因此我将使用仅异步接口(interface),如下所示:

    public interface ISpecification
    {
      Task<bool> IsSatisfiedByAsync(object candidate);
    }
    

    如果您的许多规范是同步的,则可以提供基类帮助:
    public abstract class SynchronousSpecificationBase : ISpecification
    {
      public virtual Task<bool> IsSatisfiedByAsync(object candidate)
      {
        return Task.FromResult(IsSatisfiedBy(candidate));
      }
      protected abstract bool IsSatisfiedBy(object candidate);
    }
    

    这样,复合 Material 将是:
    public class AndSpecification : ISpecification
    {
      ...
    
      public async Task<bool> IsSatisfiedByAsync(object o)
      {
        return await leftCondition.IsSatisfiedByAsync(o) && await rightCondition.IsSatisfiedByAsync(o);
      }
    }
    
    public static class SpecificationExtensions
    {
      public static ISpecification And(ISpeicification @this, ISpecification other) =>
          new AndSpecification(@this, other);
    }
    

    以及这样的个别规范:
    public class FileExistsSpecification : ISpecification
    {
      public async Task<bool> IsSatisfiedByAsync(object o)
      {
        return await _fileStorage.FileExistsAsync(addRequest.FileName);
      }
    }
    
    public class FileNameSpecification : SynchronousSpecification
    {
      private static readonly char[] _invalidEndingCharacters = { '.', '/' };
    
      public override bool IsSatisfiedBy(object o)
      {
        var request = (AddRequest)o;
        if (string.IsNullOrEmpty(request.FileName))
          return false;
        if (request.FileName.Length > 1024)
          return false;
        if (request.FileName.Contains('\\') || _invalidEndingCharacters.Contains(request.FileName.Last()))
          return false;
        return true;
      }
    }
    

    用法:
    var validations = new FileNameSpecification().And(new FileExistsSpecification());
    if (await validations.IsSatisfiedByAsync(addRequest))
    { ... }
    

    关于c# - 规范模式异步,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45676819/

    10-10 21:34
    查看更多