The*_*Mar 22 .net c# domain-driven-design n-tier-architecture
以前曾问过类似的问题,但不完全相同(除非我错过了)
我想通过我的服务,域,域事件,域事件处理程序传递IUserInfo类实例...
什么是最好的方法.
我是不是该
使用IoC通过将其注册到Httpcontext.Current.session ["CurrentUser"]的实例来注入它;
将数据添加到当前线程.
任何其他方式
我被困在域事件处理程序中,我想使用这些数据进行审计以及发送电子邮件.
我希望能够在我的应用程序中的任何位置使用CurrentUser信息.
随着线程被合并的线程,我怀疑线程的重用是否会重置数据.如果没有,请告诉我如何使用线程传递IUser实例.
问候,
损伤
Arn*_*psa 16
我的方法可能不太理想,但我觉得它运作得很好.我做了什么 - 我决定不使用依赖注入直接传递给当前用户,因为这太麻烦并且切换到静态上下文.上下文问题 - 它们有点难以管理.
这个在我的域名中定义:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,委托是静态的 - 对于整个应用程序一次只有一个.而且我不是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;
}
}
Run Code Online (Sandbox Code Playgroud)
使用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;
}
Run Code Online (Sandbox Code Playgroud)
为了将表单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.");
}
}
Run Code Online (Sandbox Code Playgroud)
很酷的是 - 这些权限可以变得更加复杂.例如:
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.");
}
}
Run Code Online (Sandbox Code Playgroud)
权限也可以反过来检查 - 用户有这些人:
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);
}
Run Code Online (Sandbox Code Playgroud)
这是我的聚合根基类:
public class Root:Entity,IRoot{
public virtual void Authorize(IUserRights rights){
UserContext.Current.CheckRightsFor(rights);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我检查权限的方式:
public class Application{
public virtual void Accept(){
Authorize(new AcceptApplications());
OpeningStatus=OpeningStatus.Accepted;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望有帮助......
在使用IoC之前我已经完成了这种事情.这样做的好处是它非常可测试 - 您可以存储用户信息以进行测试 - 并且具有合理的可读性和易于遵循的特性.