业务层验证:如何调用服务方法?
Validation in Business Layer: How to call service methods?
我已经创建了一个基于Steven's answer.
的业务层模型验证结构
它运行良好,但有些事情让我感到困惑。我在 CreateUserValidator
中注入 UserService
以能够使用 GetUser
方法。这意味着我在 UserService 中调用验证器并创建一个新的 UserService 实例来检查用户是否存在。
UserService -> [ValidateUser -> new UserService().GetUser()]
它有效,但似乎是一个非常糟糕的设计。但是我不得不使用那个方法。
能否请您告诉我如何解决这个问题,或者我不应该担心吗?
public class CreateUser
{
public string Name { get; set; }
public string Email { get; set; }
}
public sealed class CreateUserValidator : Validator<CreateUser>
{
private IUserService _userService;
public CreateUserValidator(IUserService userService)
{
_userService = userService;
}
protected override IEnumerable<ValidationResult> Validate(
CreateUser entity)
{
var user = _userService.GetUserByEmail(entity.Email);
if (user != null)
{
yield return new ValidationResult("Email", "Email address is already exist!");
}
}
}
UserService.cs
public partial class UserService : IUserService
{
IGenericUnitofWork _uow = null;
private readonly IValidationProvider _validationProvider;
public UserService(IGenericUnitofWork uow, IValidationProvider validationProvider)
{
_uow = uow;
_validationProvider = validationProvider;
}
public User CreateUser(CreateUser createUser)
{
this._validationProvider.Validate(createUser);
var user = new User()
{
Email = createUser.Email,
Name = createUser.Name,
};
_uow.Repository<User>().Insert(User);
_uow.SaveChanges();
return user;
}
public User GetUser(string email)
{
var user = _uow.Repository<User>().Where(m => m.Email == email).FirstOrDefault();
return user;
}
}
你的依赖图是循环的。如section 6.3 of Dependency Injection in .NET second edition, dependency cycles are often caused by Single Responsibility Principle 所述违规,如您所设计。
问题是 UserService
的职责太多:创建用户与获取用户是不同的职责。创建用户可能会成为一个非常复杂的用例,正如验证逻辑所暗示的那样,而获取用户通常非常简单。因此,将 UserService
拆分为多个较小的 class 是有益的。这将允许验证器依赖于允许通过邮件地址检索用户的服务,而 'create user' 服务可以依赖于验证器。
要更进一步,您可能需要从 'create user' 服务中完全删除验证。验证是一个横切关注点,将其与包含业务逻辑的 class 混合在一起,使得 class 更难维护。
一种可能对您有益的设计是将所有状态更改业务操作置于通用抽象之后,如 here 所述。
我已经创建了一个基于Steven's answer.
的业务层模型验证结构它运行良好,但有些事情让我感到困惑。我在 CreateUserValidator
中注入 UserService
以能够使用 GetUser
方法。这意味着我在 UserService 中调用验证器并创建一个新的 UserService 实例来检查用户是否存在。
UserService -> [ValidateUser -> new UserService().GetUser()]
它有效,但似乎是一个非常糟糕的设计。但是我不得不使用那个方法。
能否请您告诉我如何解决这个问题,或者我不应该担心吗?
public class CreateUser
{
public string Name { get; set; }
public string Email { get; set; }
}
public sealed class CreateUserValidator : Validator<CreateUser>
{
private IUserService _userService;
public CreateUserValidator(IUserService userService)
{
_userService = userService;
}
protected override IEnumerable<ValidationResult> Validate(
CreateUser entity)
{
var user = _userService.GetUserByEmail(entity.Email);
if (user != null)
{
yield return new ValidationResult("Email", "Email address is already exist!");
}
}
}
UserService.cs
public partial class UserService : IUserService
{
IGenericUnitofWork _uow = null;
private readonly IValidationProvider _validationProvider;
public UserService(IGenericUnitofWork uow, IValidationProvider validationProvider)
{
_uow = uow;
_validationProvider = validationProvider;
}
public User CreateUser(CreateUser createUser)
{
this._validationProvider.Validate(createUser);
var user = new User()
{
Email = createUser.Email,
Name = createUser.Name,
};
_uow.Repository<User>().Insert(User);
_uow.SaveChanges();
return user;
}
public User GetUser(string email)
{
var user = _uow.Repository<User>().Where(m => m.Email == email).FirstOrDefault();
return user;
}
}
你的依赖图是循环的。如section 6.3 of Dependency Injection in .NET second edition, dependency cycles are often caused by Single Responsibility Principle 所述违规,如您所设计。
问题是 UserService
的职责太多:创建用户与获取用户是不同的职责。创建用户可能会成为一个非常复杂的用例,正如验证逻辑所暗示的那样,而获取用户通常非常简单。因此,将 UserService
拆分为多个较小的 class 是有益的。这将允许验证器依赖于允许通过邮件地址检索用户的服务,而 'create user' 服务可以依赖于验证器。
要更进一步,您可能需要从 'create user' 服务中完全删除验证。验证是一个横切关注点,将其与包含业务逻辑的 class 混合在一起,使得 class 更难维护。
一种可能对您有益的设计是将所有状态更改业务操作置于通用抽象之后,如 here 所述。