Кэширование дорогостоящего объекта для потока, используя DI, без блокировки (асинхронно) - PullRequest
0 голосов
/ 24 августа 2018

У меня есть дорогой объект "текущий пользователь", который я хочу кэшировать на время запроса. Для этого я использую встроенный DI в ядре asp.net, чтобы создать объект ICurrentUser по запросу. Это выглядит так:

public class CurrentUserCache : ICurrentUser
{
    public CurrentUserCache(IHttpContextAccessor httpContextAccessor, UserManager userManager)
    {
        var httpContextAccessor1 = httpContextAccessor;
        _user = new Lazy<User>(() => httpContextAccessor1.HttpContext.User != null ? userManager.GetUserAsync(httpContextAccessor1.HttpContext.User).Result : null);
    }

    private Lazy<User> _user;
    public User User {
        get => _user.Value;
        set {}
    }

}

Он использует объект Lazy для отсрочки извлечения объекта, поскольку некоторые действия контроллера могут не требовать его использования.

Моя проблема - код внутри ленивого пользователя, блокирующий (.Result). Я не хочу этого делать, потому что это довольно дорого.

Я не знаю, как сделать этот код асинхронным. Я мог бы создать Lazy<Task<user>> для получения пользователя, но тогда я не могу await, что в моем свойстве пользователя, потому что это свойство и свойства не могут быть асинхронными.

Итак - как я могу превратить этот код во что-то, что хорошо работает для асинхронного?

Спасибо!

1 Ответ

0 голосов
/ 24 августа 2018

Преврати свойство в ожидаемую функцию

public class CurrentUserCache : ICurrentUser {
    public CurrentUserCache(IHttpContextAccessor httpContextAccessor, UserManager userManager) {
        _user = new Lazy<Task<User>>(() => 
            userManager.GetUserAsync(httpContextAccessor.HttpContext.User)
        );
    }

    private Lazy<Task<User>> _user;

    public Task<User> GetUserAsync() {
        return _user.Value;
    }    
}
...