c# - 如何将当前用户信息传递到 DDD 中的所有层

标签 c# .net domain-driven-design n-tier-architecture

类似的问题以前也问过但不太一样(除非我漏了)

我想通过我的服务、域、域事件、域事件处理程序传递 IUserInfo 类实例...

什么是最好的方法。

我应该

  • 通过注册它使用 IoC 注入(inject)它 针对 Httpcontext.Current.session["CurrentUser"] 的实例;

  • 将数据添加到当前线程。

  • 任何其他方式

我被困在域事件处理程序中,我想在其中使用数据进行审计和发送电子邮件。

我希望能够在我的应用程序的几乎任何位置使用 CurrentUser 信息。

随着线程被池化,我怀疑线程的重用是否会重置数据。如果没有,请告诉我如何使用线程传递 IUser 实例。

问候,

三月

最佳答案

我的方法可能并不理想,但我发现它非常有效。我所做的事情 - 我决定不使用依赖注入(inject)直接将当前用户传递到任何地方,因为这变得太麻烦并切换到静态上下文。上下文问题 - 它们有点难以管理。

这个是在我的域中定义的:

public static class UserContext{
  private static Func<User> _getCurrentUser;
  private static bool _initialized;
  public static User Current{
    get{
      if(!_initialized) 
        throw new Exception("Can i haz getCurrentUser delegate?");
      var user=_getCurrentUser();
      return user??User.Anonymous;
    }
  }
  public static void Initialize(Func<User> getCurrentUser){
    _getCurrentUser=getCurrentUser;
    _initialized=true;
  }
}

请注意,委托(delegate)是静态的 - 对于整个应用,一次只能委托(delegate)一个。而且我不能 100% 确定它的生命周期、可能的内存泄漏或诸如此类的问题。

客户端应用程序负责初始化上下文。我的 Web 应用程序会根据每个请求执行此操作:

public class UserContextTask:BootstrapperTask{
 private readonly IUserSession _userSession;
 public UserContextTask(IUserSession userSession){
   Guard.AgainstNull(userSession);
   _userSession=userSession;
 }
 public override TaskContinuation Execute(){
   UserContext.Initialize(()=>_userSession.GetCurrentUser());
   return TaskContinuation.Continue;
 }
}

使用 mvcextensions库来简化引导任务。您可以为此订阅 global.asax 中的相应事件。

在客户端(Web 应用程序),我实现了名为 IUserSession 的应用程序服务:

public User GetCurrentUser(){
  if(HttpContext.Current.User==null) return null;
  var identity=HttpContext.Current.User.Identity;
  if(!identity.IsAuthenticated) return null;
  var user=_repository.ByUserName(identity.Name);
  if(user==null) throw new Exception("User not found. It should be. Looks bad.");
  return user;
}

还有一些lame code为了使用没有成员资格提供者和角色提供者的角色的表单例份验证是必要的。但这不是这个问题的重点。

在域级别 - 我明确描述了用户可能拥有的权限,如下所示:

public class AcceptApplications:IUserRights{
  public bool IsSatisfiedBy(User u){
    return u.IsInAnyRole(Role.JTS,Role.Secretary);
  }
  public void CheckRightsFor(User u){
    if(!IsSatisfiedBy(u)) throw new ApplicationException
      ("User is not authorized to accept applications.");
  }
}

很酷的是 - 这些权限可以变得更加复杂。例如:

public class FillQualityAssessment:IUserRights{
  private readonly Application _application;
  public FillQualityAssessment(Application application){
    Guard.AgainstNull(application,
      "User rights check failed. Application not specified.");
    _application=application;
  }
  public bool IsSatisfiedBy(User u){
    return u.IsInRole(Role.Assessor)&&_application.Assessors.Contains(u);
  }
  public void CheckRightsFor(User u){
    if(!IsSatisfiedBy(u))
      throw new ApplicationException
        ("User is not authorized to fill quality assessment.");
    }
  }

权限也可以反之亦然检查 - 用户有这些家伙:

public virtual bool HasRightsTo<T>(T authorizationSpec) where T:IUserRights{
  return authorizationSpec.IsSatisfiedBy(this);
}
public virtual void CheckRightsFor<T>(T authorizationSpec) where T:IUserRights{
  authorizationSpec.CheckRightsFor(this);
}

这是我的聚合根基类:

public class Root:Entity,IRoot{
  public virtual void Authorize(IUserRights rights){
    UserContext.Current.CheckRightsFor(rights);
  }
}

这是我检查权限的方式:

public class Application{
  public virtual void Accept(){
    Authorize(new AcceptApplications());
    OpeningStatus=OpeningStatus.Accepted;
  }
}

希望对你有帮助...

关于c# - 如何将当前用户信息传递到 DDD 中的所有层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3964989/

相关文章:

c# - 防止反序列化 DateTime 值时进行时区转换

c# - get 和 set 函数在 C++ 程序员中很流行吗?

c# - Xml解析器 : XSLT compiler error

.net - 序列化的 NHibernate 配置对象 - 检测过时或按需重建?

c# - 通过Nest中的SearchRequest类设置索引名称

c# - TDD 与 DDD MVC

c# - asp.net MVC 中的 JSON 序列化

c# - 如何从打开的流中检测文件重命名

java - Spring实体和业务逻辑?

c# - 具有类层次结构的 NHibernate 映射,其基类是抽象的且鉴别器不是字符串