【问题标题】:Issue calling a generic common repository's method调用通用公共存储库的方法的问题
【发布时间】:2019-09-03 16:34:09
【问题描述】:

我有一个基础存储库设置。我想创建一个通用的通用存储库以使用一个返回布尔值的通用方法:

DoesRecordExist()

我有基本 repo 和 common repo 设置,但我在引用服务中的 ICommonRepository 时遇到问题。这个方法怎么调用?

BaseRepository:

   public abstract class BaseRepository<TModel> : IBaseRepository<TModel> where TModel : BaseClass
    {
        private readonly IDbContext _context;
        private readonly IValidator<TModel> _validator;

        public BaseRepository(IDbContext context, IValidator<TModel> validator = null)
        {
            _context = context;
            _validator = validator ?? new InlineValidator<TModel>();
        }

        public bool DoesRecordExist(Guid id)
        {
            return _context.Set<TModel>().Any(x => x.Guid == id);
        }
    }

CommonRepository:

 public  class CommonRepository<TModel> : BaseRepository<TModel> where TModel : BaseClass, ICommonRepository<TModel>
{
    private readonly IDbContext _context;
    private readonly IValidator<TModel> _validator;
    public CommonRepository(IDbContext context, IValidator<TModel> validator = null) : base(context, validator)
    {
        _context = context;
        _validator = validator ?? new InlineValidator<TModel>();
    }
    public bool CommonDoesRecordExist(Guid id)
    {
        return DoesRecordExist(id);
    }
}

全球服务:

private readonly ICategoryRepository _categoryRepository;
private readonly ISubcategoryRepository _subCategoryRepository;
private readonly ISubcategoryDescriptionRepository _subcategoryDescriptionRepository;
private readonly ICommonRepository<??????> _commonRepository;

public GlobalDataService(
    ICategoryRepository categoryRepository, 
    ISubcategoryRepository subCategoryRepository, 
    ISubcategoryDescriptionRepository subcategoryDescriptionRepository, 
    ICommonRepository<????> commonRepository)
{
    _categoryRepository = categoryRepository;
    _subCategoryRepository = subCategoryRepository;
    _subcategoryDescriptionRepository = subcategoryDescriptionRepository;
    _commonRepository = commonRepository;
}

 public bool DoesUserRecordExist(Guid userId)
    {
        //PROBLEM ON THIS LINE... bool existingData = _commonRepository.CommonDoesRecordExist(userId); 
            if (existingData)
            {
                //do stuff
            }
            else
            {
                //do other stuff
            }
        }

ICommonRepository.cs

   public interface ICommonRepository<T> : IBaseRepository
    {
        bool CommonDoesRecordExist(Guid id);
    }

IBaseRepository.cs

public interface IBaseRepository<T> : IBaseRepository
{
    bool DeleteAll();
    bool DoesRecordExist(Guid id, Expression<Func<T, bool>> filter);
    List<T> GetAll();
    T GetOne(Guid id);
    T Save(T item);
    bool Delete(Guid id);
    bool Delete(T item);
    IQueryable<T> Include(params Expression<Func<T, object>>[] includes);

}

public interface IBaseRepository
{
    string CollectionName { get; }
}

【问题讨论】:

  • 是 _commonRepository 是 BaseRepository 类型吗?
  • @stinepike 是的,它表明在我相信的代码示例中
  • 你为什么不直接调用 _commonRepository.DoesRecordExist 呢?
  • @stinepike 现在我不知道如何定义 _commonRepository 来调用它
  • 然后您将需要一个具有通用方法的工厂来获取所需的存储库

标签: c# oop generics abstract-class


【解决方案1】:

然后,您将需要一个具有通用方法的工厂来获取所需的存储库

public interface ICommonProvider {
    ICommonRepository<T> GetRepository<T>();
}

public class CommonProvider : ICommonProvider {
    private readonly ILifetimeScope lifetimeScope;

    public CommonProvider(ILifetimeScope lifetimeScope) {
        this.lifetimeScope = lifetimeScope;
    }

    public ICommonRepository<T> GetRepository<T>() {
        return lifetimeScope.Resolve<ICommonRepository<T>>();
    }
}

在启动时注册

builder.RegisterType<CommonProvider>().As<ICommonProvider>();

并将其注入到服务中

//...removed for brevity

private readonly ICommonProvider commonProvider;

public GlobalDataService(
    ICategoryRepository categoryRepository, 
    ISubcategoryRepository subCategoryRepository, 
    ISubcategoryDescriptionRepository subcategoryDescriptionRepository, 
    ICommonProvider commonProvider) {

    //...removed for brevity

    this.commonProvider = commonProvider;
}

public bool DoesUserRecordExist(Guid userId) {
    ICommonRepository<User> repository = commonProvider.GetRepository<User>();
    var existingData = repository.CommonDoesRecordExist(userId);
    if (existingData) {
        //do stuff
    } else {
        //do other stuff
    }
}

//...

也就是说,我建议放弃全局数据服务,并在更可靠的方法中遵循显式依赖原则。

简单示例

public class UserService {
    private ICommonRepository<User> repository;

    public UserService(ICommonRepository<User> repository) {
        this.repository = repository;
    }

    public bool DoesUserRecordExist(Guid userId) {
        var existingData = repository.DoesRecordExist(userId);
        if (existingData) {
            //do stuff
        } else {
            //do other stuff
        }
    }        
}

并在您的 DI 容器中注册,例如

builder.RegisterGeneric(typeof(CommonRepository<>))
    .As(typeof(ICommonRepository<>))
    .InstancePerLifetimeScope();

参考Autofac: Registration Concepts - Open Generic Components

【讨论】:

    【解决方案2】:

    您不能使用父类引用直接调用子类的方法。您需要将_commonRepository 转换为CommonRepository

    但是,如果CommonDoesRecordExist 只返回DoesRecordExist,那你为什么不直接调用DoesRecordExist

    【讨论】:

    • 我认为我现在的问题是 _commonRepository 在服务中没有定义。所以我现在无法引用任何方法。
    • 如何在我的服务中直接调用 DoesRecordExist??
    猜你喜欢
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 2014-08-03
    相关资源
    最近更新 更多