ABP 中规约的使用

25 阅读1分钟

定义规约:创建一个由 Specification 派生的新规约类

IsSatisfiedBy 方法可以用于检查单个对象是否满足规约

ToExpression 将规约转换为表达式,规约可以与And、Or、Not以及AndNot扩展方法组合使用

    public class Customer : AggregateRoot<Guid>
    {
        public string Name { get; set; }

        public byte Age { get; set; }

        public long Balance { get; set; }

        public string Location { get; set; }
    }

    //可以直接实现ISpecification<T>接口,但是基类Specification<T>做了大量简化.
    public class Age18PlusCustomerSpecification : Specification<Customer>
    {
        public override Expression<Func<Customer, bool>> ToExpression()
        {
        	//只需通过定义一个lambda表达式来定义规约
            return c => c.Age >= 18;

        	
        	return (customer) => (customer.Balance >= 100000);
        }

    }

    public class CustomerService : ITransientDependency
    {
        public async Task BuyAlcohol(Customer customer)
        {
        	//IsSatisfiedBy 方法可以用于检查单个对象是否满足规约
            if (!new Age18PlusCustomerSpecification().IsSatisfiedBy(customer))
            {
            	//如果顾客不满足年龄规定,则抛出异常
                throw new Exception(
                    "这位顾客不满足年龄规定!"
                );
            }
            
            //TODO...
        }
    }
    public class CustomerManager : DomainService, ITransientDependency
    {
        private readonly IRepository<Customer, Guid> _customerRepository;

        public CustomerManager(IRepository<Customer, Guid> customerRepository)
        {
            _customerRepository = customerRepository;
        }

        public async Task<List<Customer>> GetCustomersCanBuyAlcohol()
        {
            var queryable = await _customerRepository.GetQueryableAsync();
            var query = queryable.Where(
            	//ToExpression() 方法可用于将规约转化为表达式.
            	//通过这种方式,你可以使用规约在数据库查询时过滤实体.
                new Age18PlusCustomerSpecification().ToExpression()
            );

        	//实际上,没有必要使用 ToExpression() 方法,因为规约会自动转换为表达式
            var query = queryable.Where(
                new Age18PlusCustomerSpecification()
            );
            
            return await AsyncExecuter.ToListAsync(query);
        }
    }

    public class CustomerManager : DomainService, ITransientDependency
    {
        private readonly IRepository<Customer, Guid> _customerRepository;

        public CustomerManager(IRepository<Customer, Guid> customerRepository)
        {
            _customerRepository = customerRepository;
        }

        public async Task<int> GetAdultPremiumCustomerCountAsync()
        {
            return await _customerRepository.CountAsync(
            	//规约可以与And、Or、Not以及AndNot扩展方法组合使用
                new Age18PlusCustomerSpecification()
                .And(new PremiumCustomerSpecification()).ToExpression()
            );
        }
    }

创建一个可以复用的规约,派生自AndSpecification

public class AdultPremiumCustomerSpecification : AndSpecification<Customer>
{
    public AdultPremiumCustomerSpecification() 
        : base(new Age18PlusCustomerSpecification(),
               new PremiumCustomerSpecification())
    {
    }
}

public async Task<int> GetAdultPremiumCustomerCountAsync()
{
    return await _customerRepository.CountAsync(
        new AdultPremiumCustomerSpecification()
    );
}

项目中应用,通过规约查询冷坯、热坯