简体   繁体   English

ASP.NET MVC和MemoryCache - 我如何使用它?

[英]ASP.NET MVC and MemoryCache - how do i use it?

I have this in my Application_Start: 我在我的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());
}

Now, in my controllers i am doing this: 现在,在我的控制器中,我这样做:

var cache = new MemoryCache("breadCrumbsNames");
var cacheItem = cache.GetCacheItem("nameOfCacheItem");

But then cacheItem is always null, what am I doing wrong? 但是然后cacheItem总是为null,我做错了什么?

I think a better option for you would be to use Ninject or some other dependency injection framework to inject your MemoryCache into the controllers as needed. 我认为更好的选择是使用Ninject或其他依赖注入框架,根据需要将MemoryCache注入控制器。

You will begin by adding Ninject and Ninject.Mvc3 (and any other related bits) to your ASP.NET MVC project. 首先,将NinjectNinject.Mvc3 (以及任何其他相关位)添加到ASP.NET MVC项目中。 If you are working in Visual Studio, you can use NuGet to do that. 如果您在Visual Studio中工作,则可以使用NuGet来执行此操作。 It is quite painless and well-automated. 它非常轻松,自动化程度很高。

The next step will be to wrap your MemoryCache into some kind of a interface, such as: 下一步是将MemoryCache包装成某种接口,例如:

public interface IMemoryCacheService
{
    MemoryCache MemoryCache
    {
        get;
        set;
    }
}

And: 和:

public class MemoryCacheService : IMemoryCacheService
{
    public MemoryCacheService()
    {
        MemoryCache = new MemoryCache();
    }

    public MemoryCache MemoryCache
    {
        get;
        set;
    }
}

Then you define a binding within Ninject so that Ninject knows that when you need something of type IMemoryCacheService , it should give you the instance of MemoryCacheService . 然后在Ninject中定义一个绑定,以便Ninject知道当你需要某种类型的IMemoryCacheService ,它应该为你提供MemoryCacheService的实例。

I will paste my own Ninject config class here. 我将在这里粘贴我自己的Ninject配置类。 The one that will be created in your project will be very similar and will be in a folder called App_Start (which will be created automatically if you use NuGet). 将在您的项目中创建的那个将非常相似,并将位于名为App_Start的文件夹中(如果您使用NuGet将自动创建)。 The class that Ninject creates by default is called NinjectWebCommon . 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>();
    }
}

Finally, your controllers will change from: 最后,您的控制器将从以下更改:

public class HomeController : Controller
{
    public ActionResult Foo()
    {
        ...
    }

    ...
}

to: 至:

public class HomeController : Controller
{
    private IMemoryCacheService memoryCacheService;

    public HomeController(IMemoryCacheService memoryCacheService)
    {
        this.memoryCacheService = memoryCacheService;
    }

    public ActionResult Foo()
    {
        // use this.memoryCacheService in your controller methods...
    }

    ...
}

Say, you made another service as well called IEmailService following the above-mentioned strategy, and you wanted IEmailService to be available in HomeController as well, then: IEmailService说,您按照上述策略制作了另一个名为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...
    }

    ...
}

Ninject will change the ASP.NET MVC controller factory to automatically provide the injected arguments to the controller constructors. Ninject将更改ASP.NET MVC控制器工厂以自动向控制器构造函数提供注入的参数。

I think this sort of approach is better in the long run that keeping global variables, etc. 我认为从长远来看,这种方法在保持全局变量等方面更好。

You are creating a new instance of MemoryCache in each controller. 您正在每个控制器中创建一个新的MemoryCache实例。 Since it is new there is nothing in it which is why you values are always null. 因为它是新的,所以它没有任何东西,这就是为什么你的值总是为空的原因。 You need to access the same instance that you created in Application_Start . 您需要访问在Application_Start创建的同一实例。 Look into using MemoryCache.Default . 考虑使用MemoryCache.Default

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM