ASP.NET MVC 5 解决方案架构改进 - 多个服务具有相同的方法和代码

ASP.NET MVC 5 solution architecture improvement - multiple services with the same methods and code

我目前正在使用 Unity 和 Entity Framework 构建 ASP.NET MVC 5 应用程序。

这是我的架构(解决方案包含多个项目):

这是我的问题:在多个服务中我有相同的方法(获取一个项目,检查它是否存在,...)并且这些方法在每个服务中都完全相同,除了它们不使用相同的存储库和相同的模型。

示例:

public IQueryable<Car> Search(string search)
{
   #region Sanitize parameters + Contracts
   Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(search), Resources.Resources.SearchRequired);

   search = StringHelper.SafePlainText(search);
   Contract.Assume(search.Length <= 100 && search.Length > 1);
   #endregion

   return _carRepository.Search(StringHelper.SafePlainText(search));
}

我想要 "extract" 这些方法,这样我就不必一遍又一遍地重新创建相同的代码。

首先,我想创建一个抽象 class 我的服务从中继承,但我不知道如何将正确的存储库传递给母亲 class。

这是我试过的:

public abstract class Service<T>
{
   public object Repository { get; set; }

   protected Service(object repository) 
   {
       Repository = repository;
   }

   public IQueryable<T> Search(string search) 
   {
      #region Sanitize parameters + Contracts
      Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(search), Resources.Resources.SearchRequired);

      search = StringHelper.SafePlainText(search);
      Contract.Assume(search.Length <= 100 && search.Length > 1);
      #endregion

      return Repository.Search(StringHelper.SafePlainText(search));
   }
}

但这当然行不通。

所以我想问问你们,如果至少有可能的话,你们是否知道我如何设法完成这项工作。

提前谢谢你,请原谅我的语言不好,我不是英语母语者。

Thibault.ce

首先,您可以从基础 class(可选)继承所有 entity framework 对象:http://fairwaytech.com/2013/09/using-a-common-base-class-across-entity-framework-database-first-entities/

然后,您可以创建一个通用 class "BaseRepository",它基于您创建的基础 class(或只是 "class")。 class 将包含所有泛型方法。在这个class中,可以使用entityframework方法"Set()"访问基础对象对应的table,其中returnstyped传入参数的DbSet .

之后您可以从 "BaseRepository" 继承所有存储库,并指定具体方法。

我用 2 tables 做了一个简单的例子:https://dotnetfiddle.net/9hurx9

感谢您的快速回答。
我设法重构了我的存储库,这是一个非常好的点,感谢您的解决方案。

但起初我的问题不是重构我的存储库,而是重构我的服务。我想执行与 Entities.Set()... 相同的过程...但是调用我的存储库。

示例:
我想从我的 CarService 中提取这个方法:

public IQueryable<Car> GetAll()
{
    return _carRepository.GetAll();
}

并将其放在一个抽象的 class 服务中。像这样的东西:

public IQueryable<T> GetAll()
{
    return Repository.GetAll();
}

但是如何将正确的存储库从 class CarService 传递到 class 服务? 其实很难解释..

但是非常感谢你的回答。它已经帮助了我。

我找到的最佳解决方案是创建一个通用的 class,它依赖于 2 种类型:存储库和实体。

A BaseService< T1, T2 > 接受参数 a "BaseRepository" 和 a "IEntity" 并且将包含所有通用方法。此 class 必须包含一个包含存储库实例的 属性。因此,您可以使用示例中所示的存储库。

然后你可以创建特定的服务 classes,比如 CarService 继承自 BaseService< CarRepository, Car >。

一个简单的例子,基于我之前回答的例子:

public class BaseService<TRepo, TEntity> where TRepo : BaseRepository<TEntity> where TEntity: IEntity
{
    public TRepo Repository { get; set; }

    public BaseService(TRepo repository)
    {
        this.Repository = repository;
    }

    public List<TEntity> GetAll()
    {
        return this.Repository.GetAll().ToList();
    }
}

public class UserService : BaseService<UserRepository, User>
{
    public UserService(UserRepository repository)
        : base(repository)
    {
    }

    public List<User> GetAllUserSortByName()
    {
        return this.Repository.GetAllUserSortByName();
    }
}

你可以这样使用它:

YourEntities entities = new YourEntities();
UserRepository repo = new UserRepository(entities);
UserService service = new UserService(repo);

List<User> users = service.GetAllUserSortByName();

如果我的回答不够清楚,请告诉我。

编辑:

最终示例:https://dotnetfiddle.net/3s5BKZ