目前,我正在使用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操作复制上面的代码。例如:使用实体&#34;角色&#34;,我有&#34; InsertRole&#34;,&#34; UpdateRole&#34;,&#34; DeleteRole&#34; ...等等实体。 因此,我尝试通过将CRUD操作提取到STATIC CLASS&#34; CommonService&#34;来重构以删除重复的代码。使用以下STATIC方法:
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操作的重复代码。 在Controller中,我只是调用CommonService.Insert(user); ... 现在对我真的很好。我仍然有正常的其他服务方法,没有CRUD的重复。 但是我想知道除了单元测试之外,这种方法是否有任何缺点(我不会对CRUD进行单元测试)。 Web环境(ASP.NET MVC)中的内存管理和并发处理是否有任何问题? 我还没有使用EF实现数据处理的并发机制(同时更新实体......)
提前致谢! MillDol。
答案 0 :(得分:2)
如果您决定保留该静态实现,请创建一个使用此实现的接口和代理类,您仍然可以对使用它的实现进行单元测试。你不想丢掉单元测试。
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
,并且您不必在幕后进行静态方法调用。
答案 1 :(得分:0)
我知道这已经很老了,但刚刚遇到这个问题,我想知道为什么不采用该静态实现并将其设为抽象类 - 类似于 BaseService。 这样你就可以有你的方法的单一实现,删除你提到的所有重复代码,但如果任何特定实体需要任何特殊处理,你仍然可以在每个特定服务实现中处理它。