我正在尝试创建低级缓存服务的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()
上调用await
。await
将在getDataCallback
返回的任务中ApplicationCachingService.GetAllAsync()
内调用。
所以这是cachingService.GetOrSetAsync
的正确调用:
var items = await cachingService.GetOrSetAsync<IList<BlogPostDataModel>>(
"BlogPostsIndex",
() => repository.GetAllAsync<BlogPostDataModel>()
);