C# 如何将当前用户信息传递到DDD中的所有层
以前也有人问过类似的问题,但不完全相同(除非我错过了) 我想通过我的服务、域、域事件、域事件处理程序传递IUserInfo类实例 什么是最好的方法 我应该吗C# 如何将当前用户信息传递到DDD中的所有层,c#,.net,domain-driven-design,n-tier-architecture,C#,.net,Domain Driven Design,N Tier Architecture,以前也有人问过类似的问题,但不完全相同(除非我错过了) 我想通过我的服务、域、域事件、域事件处理程序传递IUserInfo类实例 什么是最好的方法 我应该吗 通过注册,使用IoC注入它 针对Httpcontext.Current.session[“CurrentUser”]的实例 将数据添加到当前线程 还有别的办法吗 我被困在域事件处理程序中,我想使用这些数据进行审计以及发送电子邮件 我希望能够在我的应用程序中的几乎任何地方使用CurrentUser信息 由于线程是池线程,我怀疑线程的重用是
- 通过注册,使用IoC注入它 针对Httpcontext.Current.session[“CurrentUser”]的实例
- 将数据添加到当前线程
- 还有别的办法吗
三月在使用国际奥委会之前,我就做过这种事情。这样做的好处是,它是非常可测试的——您可以删除用户信息进行测试——并且可读性强,易于理解。我的方法可能并不理想,但我发现它工作得很好。我所做的事情-我决定不使用依赖项注入直接将当前用户传递到任何地方,因为这太麻烦了,并且切换到了静态上下文。上下文的问题-它们有点难以管理 这是在我的域中定义的:
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;
}
}
使用库来流式处理行引导任务。您只需在global.asax中订阅相应的事件即可
在客户端(web应用程序)中,我实现了名为:
为了将forms auth与角色一起使用(不包括成员资格提供程序和角色提供程序),还有一些更为必要的功能。但这不是这个问题的重点
在域级别-我明确描述了用户可能拥有的权限,如:
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.");
}
}
权限也可以通过vica versa进行检查-用户有以下几项:
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 Application{
public virtual void Accept(){
Authorize(new AcceptApplications());
OpeningStatus=OpeningStatus.Accepted;
}
}
我希望这有助于……谢谢。我将再等一天,看看是否还有其他人有其他想法。按照IoC的方式,您是否先将其存储在Httpcontext.Current.session[“CurrentUser”]中?我不会将其存储在session中,而是存储在Httpcontext.Items中。会话是持久化的,但HttpContext。项只在请求的生命周期内存在,因此它非常适合这样的情况。我可能误解了某些内容,但是如何从所有层访问HttpContext,例如,domain对HttpContext一点也不了解?@Arnis-感谢您提供了详细的示例。从代码的可读性考虑,我倾向于采用IoC的方式,而不必考虑维护静态类。我仍然会在实际操作中尝试一下,我认为这可以简化一点,但仍然会受到HttpContext的依赖,这意味着它不是很可测试的。通过使用IoC,您可以在网站上使用HttpContext,但可以通过任何您想要的测试。在我看来,这是一个巨大的优势。在我的例子中,河马有控制反转。将委托传递给
Initialize
函数是IoC。上下文本身不知道如何获取当前用户。UserSession实现位于web应用程序中,该域没有技术问题。它是可测试的-我只需要用我需要的东西初始化它。唯一不好的是-它是静态的,我从上面看不到是否有任何东西会使用UserContext。@statichippo,但这就是全部的想法-避免将当前用户直接传递到任何地方,像任何地方一样隐式依赖UserContext(因为你不知道下面是什么)。@Arnis-我真的很喜欢你的异常消息!我只是想指出,我最近提出的关于允许存储库了解用户上下文的问题与我的问题有一些重叠。我一直在试图解决这个问题,以及使用用户上下文访问其他用户上下文敏感值的问题。
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;
}
}