首页 > 解决方案 > 对实现通用服务的抽象类实现不同的具体化

问题描述

我有一个通用接口和一个具有通用方法的通用类来查询数据库。

    public interface IRepositoryBase<Entity> {
        IEnumerable<TEntity> GetAll(Func<IQueryable<TEntity>, IncludableQueryable<TEntity, object>> include = null);
    }

    public class RepositoryBase<TEntity> 
        : IDisposable, IRepositoryBase<TEntity>
        where TEntity : class
    {
        public IEnumerable<TEntity> GetAll(Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null)
        {
            IQueryable<TEntity> query = _context.Set<TEntity>();

            if (include != null)
                query = include(query);

            return query.ToList();
        }
    }

我还有几个我称之为“服务”的类,它们具有业务逻辑并实现另一个通用接口。

    public interface IServiceBase<TEntity>
        where TEntity : class
    {
        IEnumerable<TEntity> GetAll(Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null);
    }

    public class ServiceBase<TEntity>
        : IDisposable, IServiceBase<TEntity> 
        where TEntity : class
    {
        private readonly IRepositoryBase<TEntity>
            _repository;

        public ServiceBase(
            IRepositoryBase<TEntity> repository)
        {
            _repository = repository;
        }

        public ServiceBase()
        {
        }

        public IEnumerable<TEntity> GetAll(Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null)
        {
            return _repository.GetAll(include);
        }
    }

    public class PizzaService : ServiceBase<Piza>, IPizzaService
    {
        private readonly IPizzaRepository _pizzaRepository;
        public PizzaService (IPizzaRepository pizzaRepository)
            : base(pizzaRepository)
        {
            _pizzaRepository= pizzaRepository;
        }
    }

这样,每个服务都有自己的方法来访问自己的表以及 ServiceBase 中的方法。

有一个场景,我有 3 个具体的服务,比如 PizzaService,每个服务都查询自己的表,代码非常相似,因为表和逻辑相似。

我想将这些具体服务重构为一个,仅更改方法参数和正在访​​问的存储库,以符合 DRY 和 ISP。

我目前拥有的:

    public interface IStopRule
    {
        string DsTerm { get; set; }
        bool ShouldDelete { get; set; }
    }

    public interface IExampleRuleStopWordsBase<TEntity> : IServiceBase<TEntity>
        where TEntity : class
    {

    }

    public abstract class ExampleRuleStopWordsBase
        : ServiceBase<IStopRule>, IExampleRuleStopWordsBase<IStopRule>
    {
        private readonly IRepositoryBase<IStopRule> _repo;

        public ExampleRuleStopWordsBase(IRepositoryBase<IStopRule> repo) 
            : base()
        {
            _repo = repo;
        }

        public virtual string ApplyRule(string input)
        {
            var terms = GetAll();
            foreach (var item in terms)
            {
                string regexPattern = @"\b(" + item.DsTerm + @")\b";
                if (item.ShouldDelete && Regex.Match(input, regexPattern, RegexOptions.IgnoreCase).Success)
                    input = input.Replace(item.DsTerm, string.Empty);
            }

            input = input.Trim();

            return input;
        }
    }

    public class PizzaService : ExampleRuleStopWordsBase, IImportRule 
    {

        public PizzaService(IRepositoryBase<IStopRule> repo)
            : base(repo)
        {
        }

        public void ApplyRule(Pizza pizza)
        {
            base.ApplyRule(pizza.Name);
        }
    }

    public class PizzaProducerService : ExampleRuleStopWordsBase, IImportRule 
    {

        public PizzaProducerService(IRepositoryBase<IStopRule> repo)
            : base(repo)
        {
        }

        public void ApplyRule(Pizza pizza)
        {
            base.ApplyRule(pizza.Producer.Name);
        }
    }

但我无法弄清楚如何将正确的实体传递给 ImportRuleStopWordsBase 的构造函数以使其使用正确的存储库......

Obs:所有接口和服务实现都驻留在领域层,而存储库的实现驻留在基础设施层。

标签: c#.netautofacgeneric-programmingabstraction

解决方案


.RegisterGeneric如果我理解正确,您似乎正在寻找这里。您的课程示例可能是:

var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<PizzaService>();
containerBuilder.RegisterType<PizzaProducerService>();

containerBuilder.RegisterGeneric(typeof(RepositoryBase<>))
    .As(typeof(IRepositoryBase<>));

var container = containerBuilder.Build();
using (var scope = container.BeginLifetimeScope())
{
    var pizzaService = scope.Resolve<PizzaService>();
    var pizzaProducerService = scope.Resolve<PizzaProducerService>();
}

推荐阅读