C# 如何使用IoC在异步服务中缓存?

C# 如何使用IoC在异步服务中缓存?,c#,asp.net-mvc,caching,asynchronous,C#,Asp.net Mvc,Caching,Asynchronous,我有一个项目,我们使用一个服务架构,用Ninject来解决我们的服务。我们几乎所有的服务都使用异步 现在,我想向几个服务添加缓存 我从未在异步方法中使用过缓存,因此我不确定如何使用它。我只知道我当前以HttpContext的形式获取此错误。Current为null: 那么,我应该采取什么策略来实现这一目标呢? 我的IoC设置:NinjectWebCommon.cs: private static void RegisterServices(IKernel kernel) {

我有一个项目,我们使用一个服务架构,用Ninject来解决我们的服务。我们几乎所有的服务都使用异步

现在,我想向几个服务添加缓存

我从未在异步方法中使用过缓存,因此我不确定如何使用它。我只知道我当前以HttpContext的形式获取此错误。Current为null:

那么,我应该采取什么策略来实现这一目标呢?

我的IoC设置:NinjectWebCommon.cs:

 private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<Context>().To<Context>().InRequestScope();
            kernel.Bind<UserManager<User>>().To<UserManager>().InTransientScope();
            kernel.Bind<IUserTokenProvider<User, string>>().ToMethod((x) =>
            {
                var provider = OwinConfig.DataProtectionProvider;
                return new DataProtectorTokenProvider<User>(provider.Create("ASP.NET Identity"));
            }).InTransientScope();

            kernel.Bind<ICacheService>().To<HttpCache>();    
            kernel.Bind<IUserService>().To<UserService>();
            // Lots of nice services

        }
缓存服务:

public interface ICacheService
{
    object GetById(string cacheKey);
    object Create(string cacheKey, object obj);
    object Create(string cacheKey, object obj, DateTime expire);
    void Delete(string cacheKey);
    void DeleteByContaining(string containing);
    string GetCacheKey(string methodName, string value);
    bool ContainsKey(string cacheKey);
}
public class HttpCache : ICacheService
    {
        private static readonly ILog logger = LogManager.GetLogger(typeof (HttpCache));


        public object GetById(string cacheKey)
        {
            if (ContainsKey(cacheKey))
            {
                return HttpContext.Current.Cache[cacheKey];
            }

            return null;
        }

        public object Create(string cacheKey, object obj)
        {
            return Create(cacheKey, obj, DateTime.UtcNow.AddHours(5));
        }

        public object Create(string cacheKey, object obj, DateTime expire)
        {
            if (!ContainsKey(cacheKey))
            {
                HttpContext.Current.Cache.Insert(cacheKey,
                    obj,
                    null,
                    expire,
                    Cache.NoSlidingExpiration);
            }
            return GetById(cacheKey);
        }

        public void Delete(string cacheKey)
        {
            HttpContext.Current.Cache.Remove(cacheKey);
        }

        public void DeleteByContaining(string containing)
        {
            List<string> deleteList = new List<string>();
            HttpContext oc = HttpContext.Current;

            // find all cache keys in the system... maybe insane? I don't know lol
            IDictionaryEnumerator en = oc.Cache.GetEnumerator();
            while (en.MoveNext())
            {
                var k = en.Key.ToString();
                if (k.Contains(containing))
                {
                    deleteList.Add(k);
                }
            }

            foreach (var del in deleteList)
            {
                Delete(del);
            }
        }


        public bool ContainsKey(string cacheKey)
        {
            return HttpContext.Current.Cache[cacheKey] != null;
        }

        public string GetCacheKey(string methodName, string value)
        {
            return string.Format("{0}_{1}", methodName, value);
        }
    }
公共类HttpCache:ICacheService
{
私有静态只读ILog logger=LogManager.GetLogger(typeof(HttpCache));
公共对象GetById(字符串缓存键)
{
if(ContainsKey(cacheKey))
{
返回HttpContext.Current.Cache[cacheKey];
}
返回null;
}
公共对象创建(字符串缓存键,对象对象obj)
{
返回Create(cacheKey,obj,DateTime.UtcNow.AddHours(5));
}
创建公共对象(字符串cacheKey、对象obj、DateTime expire)
{
如果(!ContainsKey(cacheKey))
{
HttpContext.Current.Cache.Insert(cacheKey,
obj,
无效的
到期,
Cache.NoSlidingExpiration);
}
返回GetById(cacheKey);
}
公共无效删除(字符串缓存键)
{
HttpContext.Current.Cache.Remove(cacheKey);
}
公共void DeleteByContaining(字符串包含)
{
List deleteList=新列表();
HttpContext oc=HttpContext.Current;
//找到系统中的所有缓存密钥…可能是疯了?我不知道哈哈
IDictionaryEnumerator en=oc.Cache.GetEnumerator();
while(en.MoveNext())
{
var k=en.Key.ToString();
如果(k.Contains(containing))
{
删除列表。添加(k);
}
}
foreach(deleteList中的变量del)
{
删除(del);
}
}
公共bool ContainsKey(字符串缓存键)
{
返回HttpContext.Current.Cache[cacheKey]!=null;
}
公共字符串GetCacheKey(字符串方法名、字符串值)
{
返回string.Format(“{0}{1}”,方法名,值);
}
}
我的来电者:

 public async Task<City> GetById(int id)
        {

            var cacheKey = _cacheService.GetCacheKey(MethodBase.GetCurrentMethod().Name, id.ToString());
            if (!_cacheService.ContainsKey(cacheKey))
            {
                var city = await _db.Cities.FirstAsync(c => c.Id == id);


                _cacheService.Create(cacheKey, city);
                return city;
            }
            return (City)_cacheService.GetById(cacheKey);
        }
public异步任务GetById(int-id)
{
var cacheKey=_cacheService.GetCacheKey(MethodBase.GetCurrentMethod().Name,id.ToString());
if(!\u cacheService.ContainsKey(cacheKey))
{
var city=await _db.Cities.FirstAsync(c=>c.Id==Id);
_创建(cacheKey,城市);
回归城市;
}
return(City)\u cacheService.GetById(cacheKey);
}

HttpContext.Current.Cache是访问ASP.Net全局缓存对象的几个快捷方式之一(请求生存时间的另一个快捷方式是)。如果需要在请求外部访问缓存,请使用。(也包括在本手册中)

注:

  • 请注意,您没有得到
    HttpContext.Current
    这一事实可能是更大问题的症状-您可能希望代码运行时设置
    HttpContext
    ,但它不是,以及区域性。。。对于您来说,这是否确实是一个问题尚待解决,但至少要检查您的代码是否意外地使用了
    .ConfigureAwait(false)
    任务。手动运行
    或安排线程池上的工作
  • 虽然从缓存中添加/读取单个项是线程安全的,但当您希望多个项保持一致时,请小心—您可能需要锁定
  • 小心不要将特定于用户的数据放在缓存中,尤其是当您的缓存处于IOC级别,并且您没有直接信息知道结果是否特定于用户时

HttpContext.Current.Cache是访问ASP.Net全局缓存对象的几个快捷方式之一(请求生存时间的另一个快捷方式是)。如果需要在请求外部访问缓存,请使用。(也包括在本手册中)

注:

  • 请注意,您没有得到
    HttpContext.Current
    这一事实可能是更大问题的症状-您可能希望代码运行时设置
    HttpContext
    ,但它不是,以及区域性。。。对于您来说,这是否确实是一个问题尚待解决,但至少要检查您的代码是否意外地使用了
    .ConfigureAwait(false)
    任务。手动运行
    或安排线程池上的工作
  • 虽然从缓存中添加/读取单个项是线程安全的,但当您希望多个项保持一致时,请小心—您可能需要锁定
  • 小心不要将特定于用户的数据放在缓存中,尤其是当您的缓存处于IOC级别,并且您没有直接信息知道结果是否特定于用户时

HttpContext.Current.Cache是访问ASP.Net全局缓存对象的几个快捷方式之一(请求生存时间的另一个快捷方式是)。如果需要在请求外部访问缓存,请使用。(也包括在本手册中)

注:

  • 请注意,您没有得到
    HttpContext.Current
    这一事实可能是更大问题的症状-您可能希望代码运行时设置
    HttpContext
    ,但它不是,以及区域性。。。对于您来说,这是否确实是一个问题尚待解决,但至少要检查您的代码是否意外地使用了
    .ConfigureAwait(false)
    任务。手动运行
    或安排线程池上的工作
  • 虽然从缓存中添加/读取单个项是线程安全的,但当您希望多个项保持一致时,请小心—您可能需要锁定
  • 小心不要将特定于用户的数据放在缓存中,特别是当您的缓存处于IOC级别,并且您没有直接信息知道结果是否为u