Я выяснил, что мне нужны текущие зарегистрированные данные пользователя почти в каждом классе (контроллеры, просмотр, HTML-помощники, службы и т.д.). Поэтому я решил создать "Окружающий контекст" вместо того, чтобы напрямую вводить IUserService или Пользователя.
Мой подход выглядит примерно так.
public class Bootstrapper
{
public void Boot()
{
var container = new Container();
// the call to IUserService.GetUser is cached per Http request
// by using a dynamic proxy caching mechanism, that also handles cases where we want to
// invalidate a cache within an Http request
UserContext.ConfigureUser = container.GetInstance<IUserService>().GetUser;
}
}
public interface IUserService
{
User GetUser();
}
public class User
{
string Name { get; set; }
}
public class UserContext : AbstractFactoryBase<User>
{
public static Func<User> ConfigureUser = NotConfigured;
public static User ActiveUser { get { return ConfigureUser(); } }
}
public class AbstractFactoryBase<T>
{
protected static T NotConfigured()
{
throw new Exception(String.Format("{0} is not configured", typeof(T).Name));
}
}
Пример использования:
public class Controller
{
public ActionResult Index()
{
var activeUser = UserContext.ActiveUser;
return View();
}
}
Правильно ли мой подход или что-то не хватает? У вас есть лучшие решения?
ОБНОВЛЕНИЕ:
Дополнительные сведения о классе Пользователь:
public class User
{
string Name { get; set; }
bool IsSuperUser { get; set;}
IEnumerable<AzManOperation> Operations { get; set}
}
В Контроллерах нам нужно проверить, является ли Пользователь суперусером, чтобы предоставить SuperUser дополнительную функциональность.
public class BaseController : Controller
{
private readonly IUserService _userService;
BaseControler(IUserService userService)
{
_userService = userService
}
public User ActiveUser
{
get { return _userService.GetUser(); }
}
}
В Представления мы проверяем операции только для отображения кнопки редактирования или удаления, если пользователь имеет на это право. В представлении никогда не используется DependencyResolver, а ViewBag или ViewModel. Моя идея здесь заключается в реализации пользовательского ViewBasePage и предоставлении свойства ActiveUser, так что Views имеет легкий доступ.
В HtmlHelpers мы обрабатываем элементы управления в зависимости от IsSuperUser и Operations (передача в объекте User или с помощью DependencyResolver).
В Сервисные классы нам нужны эти свойства. Например, чтобы решить, действительна ли корзина или нет (проверьте, разрешено ли пользователю покупать статьи, которые не входят в стандартный список). Таким образом, класс службы зависит от IUserService
и вызывает GetUser()
.
В Action Filters, чтобы заставить пользователя изменить свой пароль (только если это не SuperUser, а User.ForcePasswordChange - true). Здесь мы используем DependencyResolver.
Мое желание состоит в том, чтобы получить более простой способ получить объект User, вместо использования DependencyResolver.Current.GetService(). GetUser() или используя такие вещи, как ViewBag.ActiveUser = User
.
Объект User - это объект, который почти везде необходим для проверки разрешений и т.п.