我在我的Application_Start中有这个:
var crumbsCache = new MemoryCache("breadCrumbsNames"); var crumbsList = new List<CacheItem> { //list of new CacheItem(); }; foreach (var cacheItem in crumbsList) { crumbsCache.Add(cacheItem,new CacheItemPolicy()); }
现在,在我的控制器中,我这样做:
var cache = new MemoryCache("breadCrumbsNames"); var cacheItem = cache.GetCacheItem("nameOfCacheItem");
但是然后cacheItem总是为null,我做错了什么?
解决方法
我认为更好的选择是使用Ninject或其他依赖注入框架,根据需要将MemoryCache注入控制器.
首先,将Ninject和Ninject.Mvc3(以及任何其他相关位)添加到ASP.NET MVC项目中.如果您在Visual Studio中工作,则可以使用NuGet来执行此操作.它非常轻松,自动化程度很高.
下一步是将MemoryCache包装成某种接口,例如:
public interface IMemoryCacheService { MemoryCache MemoryCache { get; set; } }
和:
public class MemoryCacheService : IMemoryCacheService { public MemoryCacheService() { MemoryCache = new MemoryCache(); } public MemoryCache MemoryCache { get; set; } }
然后在Ninject中定义一个绑定,以便Ninject知道当你需要某种类型的IMemoryCacheService时,它应该为你提供MemoryCacheService的实例.
我将在这里粘贴我自己的Ninject配置类.将在您的项目中创建的那个将非常相似,并将位于名为App_Start的文件夹中(如果您使用NuGet将自动创建). Ninject默认创建的类称为NinjectWebCommon.
public static class NinjectConfig { private static readonly Bootstrapper bootstrapper = new Bootstrapper(); public static void Start() { DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule)); DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule)); bootstrapper.Initialize(CreateKernel); } public static void Stop() { bootstrapper.ShutDown(); } private static IKernel CreateKernel() { var kernel = new StandardKernel(); kernel.Bind<Func<IKernel>>() .ToMethod(context => () => new Bootstrapper().Kernel); kernel.Bind<IHttpModule>() .To<HttpApplicationInitializationHttpModule>(); kernel.RegisterServices(); return kernel; } private static void RegisterServices(this IKernel kernel) { kernel.Bind<IMemoryCacheService>() .To<MemoryCacheService>() .InSingletonScope(); // InSingletonScope() is important so Ninject knows // to create only one copy and then reuse it every time // it is asked for // ignore the stuff below... I have left it in here for illustration kernel.Bind<IDbTransactionFactory>() .To<DbTransactionFactory>() .InRequestScope(); kernel.Bind<IDbModelContext>() .To<DbModelContext>() .InRequestScope(); kernel.Bind<IDbModelChangeContext>() .To<DbModelChangeContext>() .InRequestScope(); kernel.Bind<IUserContext>() .To<UserContext>() .InRequestScope(); kernel.BindAttributeAndFilter<IgnoreNonAjaxRequestsFilter,IgnoreNonAjaxRequestsAttribute>(); kernel.BindAttributeAndFilter<ProvideApplicationInfoFilter,ProvideApplicationInfoAttribute>(); kernel.BindAttributeAndFilter<ProvideSessionInfoFilter,ProvideSessionInfoAttribute>(); kernel.BindAttributeAndFilter<UseDialogLayoutFilter,UseDialogLayoutAttribute>(); kernel.BindAttributeAndFilter<CheckResourceAccessFilter,CheckResourceAccessAttribute>(); kernel.BindAttributeAndFilter<CheckResourceStateFilter,CheckResourceStateAttribute>(); } private static void BindAttributeAndFilter<TFilter,TAttribute>(this IKernel kernel) { kernel.BindFilter<TFilter>(FilterScope.Action,null) .WhenControllerHas<TAttribute>(); kernel.BindFilter<TFilter>(FilterScope.Action,null) .WhenActionMethodHas<TAttribute>(); } }
最后,您的控制器将从以下更改:
public class HomeController : Controller { public ActionResult Foo() { ... } ... }
至:
public class HomeController : Controller { private IMemoryCacheService memoryCacheService; public HomeController(IMemoryCacheService memoryCacheService) { this.memoryCacheService = memoryCacheService; } public ActionResult Foo() { // use this.memoryCacheService in your controller methods... } ... }
比方说,您按照上述策略制作了另一个名为IEmailService的服务,并且您希望IEmailService也可以在HomeController中使用,然后:
public class HomeController : Controller { private IMemoryCacheService memoryCacheService; private IEmailService emailService; public HomeController(IMemoryCacheService memoryCacheService,IEmailService emailService) { this.memoryCacheService = memoryCacheService; this.emailService = emailService; } public ActionResult Foo() { // use this.memoryCacheService in your controller methods... // and also use this.emailService in your controller methods... } ... }