我发现我几乎每个类(控制器,视图,HTML帮助程序,服务等)都需要当前登录的用户数据。所以我想创建一个“环境上下文”而不是直接注入IUserService或User。
我的方法看起来像那样。
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}
}
在 控制器 我们需要检查用户是否是超级用户才能为超级用户提供一些额外的功能。
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)。
在 服务类 我们也需要那些属性。例如,判断篮子是否有效(检查是否允许用户购买不在标准列表中的文章)。所以Service类依赖于 IUserService
并打电话 GetUser()
。
在 动作过滤器 强制用户更改密码(仅当它不是SuperUser并且User.ForcePasswordChange为true时)。这里我们使用DependencyResolver。
我希望有一个更简单的方法来获取User对象,而不是使用DependencyResolver.Current.GetService()。GetUser()或使用像 ViewBag.ActiveUser = User
。
User对象是几乎到处检查权限等所需的对象。