典型 3 层业务层中的静态方法与实例方法

本文关键字:静态方法 实例方法 业务 典型 | 更新日期: 2023-09-27 18:33:31

目前,我正在使用 ASP.NET MVC构建一个典型的3层Web应用程序。我已经使用依赖注入(Autofac(设置了它,如下所示:

public class UserController : BaseController
{
    private readonly IUserService _userService;
    public UserController(IUserService userService)
    {
        this._userService = userService;
    }
}
public class IUserService
{
    void InsertUser(User user);
    void UpdateUser(User user);
    void DeleteUser(User user);
}
public class UserService : IUserService
{
    private readonly IRepository<User> _userRepository;
    public UserService(IRepository<User> userRepository)
    {
        this._userRepository = userRepository;
    }
    public void InsertUser(User user)
    {
        _userRepository.Insert(user);
    }
    public void UpdateUser(User user)
    {
        _userRepository.Update(user);
    }
    public void DeleteUser(User user)
    {
        _userRepository.Delete(user);
    }
}

存储库是使用 EF 的典型通用存储库。

public interface IRepository<T> where T : BaseEntity
{
    void Insert(T entity);
    void Update(T entity);
    void Delete(T entity);
}

问题是我的应用程序有很多实体,对于每个实体,我必须在服务层中复制上述代码以进行 CRUD 操作。例如:对于实体"角色",我有"插入角色"、"更新角色"、"删除角色"......以及其他实体的更多内容。因此,我尝试重构以删除重复的代码,方法是使用静态方法将 CRUD 操作提取到静态类"CommonService"中,如下所示:

public static class CommonService
{
    public static void Insert<T>(T entity) where T : BaseEntity
    {
        var repository = EngineContext.Current.Resolve<IRepository<T>>();
        repository.Insert(entity);
    }
    public static void Update<T>(T entity) where T : BaseEntity
    {
        var repository = EngineContext.Current.Resolve<IRepository<T>>();
        repository.Update(entity);
    }
    public static void Delete<T>(T entity) where T : BaseEntity
    {
        var repository = EngineContext.Current.Resolve<IRepository<T>>();
        repository.Delete(entity);
    }
}

使用此类,我将删除 CRUD 操作的重复代码。在控制器中,我只调用 CommonService.Insert(user(;...现在对我真的很好。我仍然有另一种正常的服务方法,并且没有重复的 CRUD。但我想知道除了单元测试之外,这种方法是否有任何缺点(我不会对 CRUD 进行单元测试(。Web 环境 (ASP.NET MVC( 中的内存管理和并发处理是否存在任何问题?我还没有实现使用 EF 处理数据的并发机制(同时更新实体...

提前感谢!米尔多尔。

典型 3 层业务层中的静态方法与实例方法

如果您决定保留该静态实现,请创建一个使用它的接口和代理类,您仍然可以对使用它的实现进行单元测试。您不想丢弃单元测试。

public interface ICommonService<T>
{
    void Insert<T>(T entity);
    void Update<T>(T entity);
    void Delete<T>(T entity);
}

并实现一个简单的代理类型,该类型实现ICommonService<T>并将调用转发到静态类。然后,您可以依靠ICommonService<T>并像以前一样模拟它,就像以前一样进行测试。


我不会有静态类。我不认识EngineContext.Current,但它看起来像服务定位器模式。通常不鼓励这样做,因为它隐藏了您从明显检查中依赖的内容。

你仍然可以有一个像ICommonService<T>这样的公共接口,然后实现代理依赖于一个IRepository<T>

public class CommonService<T> : ICommonService<T> where T : BaseEntity
{
    private readonly IRepository<T> repository;
    public CommonService(IRepository<T> repository)
    {  
        if (repository == null) throw new ArgumentNullException(nameof(repository)); 
        this.repository = repository;
    }
    // and other methods
}

然后你可以让你的控制器依赖于ICommonService,你不必在后台进行静态方法调用。

我知道

这很老了,但刚刚遇到这个,我想知道你为什么不直接采用静态实现并使其成为一个抽象类 - 类似于 BaseService。这样,你可以有一个方法的实现,删除你提到的所有重复代码,但如果任何特定的实体需要任何特殊处理,你可以在每个特定的服务实现中处理它。