Ответ 1
Я делал это, прежде чем использовать IoC. Преимущество этого в том, что он очень поддается тестированию - вы можете заглушить информацию о пользователе для тестирования - и достаточно читабельны и легко следовать.
Схожие вопросы задавали раньше, но не совсем то же самое (если я не пропустил это)
Я хочу передать экземпляр класса IUserInfo через мои службы, домен, события домена, обработчики событий домена...
Каков наилучший способ сделать это.
Должен ли я
Внесите его с помощью IoC, зарегистрировав его против экземпляра Httpcontext.Current.session [ "CurrentUser" ];
Добавьте данные в текущую тему.
Любой другой способ
Я застрял в обработчиках событий домена, где я хочу использовать данные для аудита, а также для отправки писем.
Я хочу иметь возможность использовать информацию CurrentUser практически из любого места в моем приложении.
С потоком, когда потоки объединены, я скептически отношусь, если повторное использование потоков будет reset данными. Если нет, пожалуйста, попробуйте мне использовать threading для передачи экземпляра IUser.
Привет,
Mar
Я делал это, прежде чем использовать IoC. Преимущество этого в том, что он очень поддается тестированию - вы можете заглушить информацию о пользователе для тестирования - и достаточно читабельны и легко следовать.
Мой подход может быть не идеальным, но я считаю, что он работает достаточно хорошо. Что я делал - я решил не использовать использовать инъекцию зависимостей, чтобы передать текущему пользователю всюду прямо, потому что это становилось слишком громоздким и переключилось на статический контекст. Проблема с контекстами - их немного сложно управлять.
Это определено в моем домене:
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;
}
}
Обратите внимание, что делегат является статическим - для всего приложения только по одному. И я не уверен на 100% об этом жизненном цикле, возможных утечках памяти или о чем-то еще.
Клиентское приложение отвечает за инициализацию контекста. Мое веб-приложение делает это по каждому запросу:
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 для этого.
На стороне клиента (веб-приложение) я реализую службу приложений с именем 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, необходимый для использования форм 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 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;
}
}
Я надеюсь, что это поможет...