如何创建和调用缓存 GetOrSet 方法的异步版本?



我正在尝试创建低级缓存服务的async版本。

标准的非异步版本是这样的:

public class ApplicationCachingService : IApplicationCacheService
{
public T GetOrSet<T>(string cacheKey, Func<T> getDataCallback) 
where T : class
{
T data = HttpContext.Current.Application[cacheKey] as T;
if (data == null)
{
data = getDataCallback();
HttpContext.Current.Application[cacheKey] = data;
}
return data;
}

public void ClearCache(string cacheKey)
{
HttpContext.Current.Application[cacheKey] = null;
}
}

我正在添加以下方法。

public async Task<T> GetOrSetAsync<T>(string cacheKey, Task<Func<T>> getDataCallback) 
where T : class
{
T data = HttpContext.Current.Application[cacheKey] as T;
if (data == null)
{
Func<Task<Func<T>>> myFunc = async () => await getDataCallback;
var funcResult = await myFunc();
data = funcResult();
HttpContext.Current.Application[cacheKey] = data;
}
return data;
}

问题 1 - 这是一种正确的方法吗?

我不确定我是否需要创建funcResult变量,或者是否有更简洁的方法来完成它。例如,这条线看起来可能是不必要的复杂Func<Task<Func<T>>> myFunc = async () => await getDataCallback;

以上是基于纯代码捏造的,作为代表明智,我是一个彻头彻尾的菜鸟。

问题 2 - 我应该如何称呼它?

我正在将此代码用于标准非异步版本:

var items = cachingService.GetOrSet<IList<BlogPostDataModel>>(
"BlogPostsIndex",
() => repository.GetAll<BlogPostDataModel>()
);

我将这段代码用于异步版本:

var items = await cachingService.GetOrSetAsync<IList<BlogPostDataModel>>(
"BlogPostsIndex",
() => await repository.GetAllAsync<BlogPostDataModel>()
);

但是异步版本给了我cannot convert lambda expression to type Task<Func<IList<BlogPostDataModel>>>' because it is not a delegate type


最终工作示例

CodeFuller在他的回答中非常有帮助,读完后我立即开始工作。以下是完成的工作代码:

public interface IApplicationCacheService
{
T GetOrSet<T>(string cacheKey, Func<T> getDataCallback) where T : class;
Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getDataCallback) where T : class;
}

public class ApplicationCachingService : IApplicationCacheService
{
public T GetOrSet<T>(string cacheKey, Func<T> getDataCallback) 
where T : class
{
T data = HttpContext.Current.Application[cacheKey] as T;
if (data == null)
{
data = getDataCallback();
HttpContext.Current.Application[cacheKey] = data;
}
return data;
}

public async Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getDataCallback) 
where T : class
{
T data = HttpContext.Current.Application[cacheKey] as T;
if (data == null)
{
data = await getDataCallback();
HttpContext.Current.Application[cacheKey] = data;
}
return data;
}

public void ClearCache(string cacheKey)
{
HttpContext.Current.Application[cacheKey] = null;
}
}

这样称呼:

var items = await cachingService.GetOrSetAsync(
cacheKey,
() => repository.GetAllAsync<BlogPostDataModel>()
);

getDataCallback的类型为Task<Func<T>>。我相信(并且从GetOrSetAsync方法的调用来看)您的意图不是拥有将返回Func<T>Task,而是传递异步值工厂,即Func<Task<T>>.

所以第一步是更改GetOrSetAsync<T>的声明:

IApplicationCacheService界面中:

Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getDataCallback) where T : class;

ApplicationCachingService课上:

public async Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getDataCallback) where T : class

现在你可以调用await getDataCallback()从回调中获取值:

public async Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getDataCallback) where T : class
{
T data = HttpContext.Current.Application[cacheKey] as T;
if (data == null)
{
data = await getDataCallback();
HttpContext.Current.Application[cacheKey] = data;
}
return data;
}

现在让我们修复对GetOrSetAsync的调用。如果存储库方法GetAllAsync声明为:

Task<IList<T>> GetAllAsync<T>() where T : class;

那么这里有一个你应该传递给IApplicationCacheService.GetOrSetAsync的lambda:

() => repository.GetAllAsync<BlogPostDataModel>()

因为GetAllAsync<BlogPostDataModel>()返回Task<IList<BlogPostDataModel>>和 lambda() => repository.GetAllAsync<BlogPostDataModel>()具有Func<Task<IList<BlogPostDataModel>>>的类型,这是IApplicationCacheService.GetOrSetAsync<IList<BlogPostDataModel>>()预期的确切类型。

而且您不应该在 lambda 中的GetAllAsync()上调用awaitawait将在getDataCallback返回的任务中ApplicationCachingService.GetAllAsync()内调用。

所以这是cachingService.GetOrSetAsync的正确调用:

var items = await cachingService.GetOrSetAsync<IList<BlogPostDataModel>>(
"BlogPostsIndex",
() => repository.GetAllAsync<BlogPostDataModel>()
);

相关内容

最新更新