2016-04-03 3 views
1

Для каждого запроса страницы, мне нужно, чтобы получить некоторые текущие данные права пользователя из базы данных, а затем использовать эту информацию несколько раз в логике (который состоит из нескольких объектов)IoC - Инициализировать состояние объекта в конструкторе

Я хочу получить данные из базы данных один раз за запрос и повторно использовать их там, где это необходимо, путем инъекции.

Это лучший способ сделать это?

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(); 
} 

ответ

1

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 связаны с этой оптимизацией производительности, что хорошо. Декоратор позволяет нам плагировать эту оптимизацию производительности, не меняя ни одного из существующих классов.

Смежные вопросы