对于每个页面请求,我需要从数据库中获取一些当前用户权限数据,然后在逻辑中多次使用此信息 (由几个对象组成)
我希望每次请求从数据库中获取一次数据,并在需要时通过注入来重用它。
以下是最好的方法吗?
1)定义一个像这样的对象
class ApplicationUser : IApplicationUserProvider
{
private UserPermissions _userPermissions;
...
public ApplicationUser(IDatabase userService)
{
_userPermissions = userService.GetUserPermission(); // this would executed for every request once
}
UserRoles GetRoles()
{
return _userPermissions;
}
}
2)定义类似这样的ioc
var container1 = new Container(c =>
{
c.For<IDatabase>().Use<Database>();
c.For<IApplicationUser>().Use<ApplicationUser >();
c.For<IApplicationLogic1>().Use<ApplicationLogic1>(); // this has IApplicationUser in ctor
c.For<IApplicationLogic2>().Use<ApplicationLogic2>(); // this has IApplicationUser in ctor
});
3)控制器将是
void PageController(IApplicationLogic1 l1)
{
l1.Process();
l2.Process();
}
答案 0 :(得分:2)
UserPermissions
信息是运行时数据,正如here所解释的那样,在构造对象图时不应注入或解析运行时数据。
相反,对userService.GetUserPermission()
的调用应该移出构造函数。例如,通过使用Lazy<T>
来延迟呼叫:
class ApplicationUser : IApplicationUserProvider
{
private Lazy<UserPermissions> _userPermissions;
public ApplicationUser(IDatabase userService) {
_userPermissions = new Lazy<UserPermissions>(userService.GetUserPermission);
}
UserRoles GetRoles() {
return _userPermissions.Value.GetRoles();
}
}
另一种选择是在IDatabase
上定义一个将实现缓存的装饰器:
public class PerRequestCacheDatabaseDecorator : IDatabase
{
private IDatabase _decoratee;
public PerRequestCacheDatabaseDecorator(IDatabase decoratee) {
_decoratee = decoratee;
}
public UserPermissions GetUserPermission() {
var items = HttpContext.Current.Items;
if (items["permissions"] == null)
items["permissions"] = _decoratee.GetUserPermission();
return (UserPermissions)items["permissions"];
}
}
通过将真实数据库包装在PerRequestCacheDatabaseDecorator
中,您可以将ApplicationUser
简化为以下内容:
class ApplicationUser : IApplicationUserProvider
{
private IDatabase _userService;
public ApplicationUser(IDatabase userService) {
_userService = userService;
}
public UserRoles GetRoles() {
return _userService.GetUserPermission().GetRoles();
}
}
现在,ApplicationUser
和Database
类都不关心这种性能优化,这是一件好事。装饰器允许我们插入此性能优化,而无需更改任何现有类。