2013-02-15 20 views
5

Tôi có điều này trong Application_Start của tôi:ASP.NET MVC và MemoryCache - làm thế nào để tôi sử dụng nó?

var crumbsCache = new MemoryCache("breadCrumbsNames"); 
var crumbsList = new List<CacheItem> 
        { 
         //list of new CacheItem(); 
        }; 
foreach (var cacheItem in crumbsList) 
{ 
    crumbsCache.Add(cacheItem, new CacheItemPolicy()); 
} 

Bây giờ, trong các bộ điều khiển của tôi đang làm điều này:

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

Nhưng sau đó cacheItem luôn luôn là null, những gì tôi làm sai?

+0

Kiểm tra này http://www.deanhume.com/home/blogpost/object-caching----net -4/37 – Mate

Trả lời

8

Bạn đang tạo một phiên bản mới MemoryCache trong mỗi bộ điều khiển. Vì nó là mới không có gì trong nó, đó là lí do tại sao bạn giá trị luôn rỗng. Bạn cần truy cập cùng một trường hợp mà bạn đã tạo trong Application_Start. Xem xét sử dụng MemoryCache.Default.

+0

Nhưng chính xác 'MemoryCache.Default' là gì? Nếu tôi thiết lập hai trường hợp memcache khác nhau, cách 'MemoryCache.Default' biết cái nào là mặc định? – ojek

+0

Đặt MemoryCache.Mặc định bằng với cá thể bạn muốn sử dụng. –

10

Tôi nghĩ rằng một lựa chọn tốt hơn cho bạn sẽ là sử dụng Ninject hoặc một số khung tiêm phụ thuộc khác để tiêm MemoryCache của bạn vào bộ điều khiển nếu cần.

Bạn sẽ bắt đầu bằng cách thêm NinjectNinject.Mvc3 (và mọi bit liên quan khác) vào dự án ASP.NET MVC của bạn. Nếu bạn đang làm việc trong Visual Studio, bạn có thể sử dụng NuGet để làm điều đó. Nó là khá đau và cũng tự động.

Bước tiếp theo sẽ là quấn MemoryCache của bạn vào một số loại của một giao diện, chẳng hạn như:

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

Và:

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

    public MemoryCache MemoryCache 
    { 
     get; 
     set; 
    } 
} 

Sau đó, bạn định nghĩa một ràng buộc trong vòng Ninject để Ninject biết khi bạn cần một cái gì đó loại IMemoryCacheService, nó sẽ cho bạn ví dụ của MemoryCacheService.

Tôi sẽ dán lớp cấu hình Ninject của riêng mình tại đây. Một trong đó sẽ được tạo ra trong dự án của bạn sẽ rất giống nhau và sẽ được trong một thư mục gọi là App_Start (sẽ được tạo tự động nếu bạn sử dụng NuGet). Lớp mà Ninject tạo ra theo mặc định được gọi là 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>(); 
    } 
} 

Cuối cùng, bộ điều khiển của bạn sẽ thay đổi từ:

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

    ... 
} 

tới:

public class HomeController : Controller 
{ 
    private IMemoryCacheService memoryCacheService; 

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

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

    ... 
} 

Này, bạn đã thực hiện một dịch vụ cũng được gọi là IEmailService sau chiến lược nêu trên, và bạn muốn IEmailService cũng có sẵn trong HomeController, sau đó:

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 sẽ thay đổi nhà máy bộ điều khiển MVC ASP.NET để tự động cung cấp các đối số được chèn vào các bộ điều khiển của bộ điều khiển.

Tôi nghĩ loại này của phương pháp là tốt hơn trong thời gian dài mà vẫn giữ các biến toàn cục vv

+3

Tôi có ý kiến ​​này cho biết thêm chi phí cao hơn giá trị cho hầu hết các tình huống. [Đã chỉnh sửa để thêm: điều này có thể thích hợp cho bộ đệm được phân phối.] Chỉ cần sử dụng MemoryCache.Default như được mô tả bởi Ryan Byrne. –

+0

Tôi đã viết tất cả những điều trên để minh họa cách tiếp cận đúng hơn là trả lời câu hỏi cụ thể, nếu tôi trung thực. Vấn đề cốt lõi là OP đã cố gắng tạo một đối tượng trong một bộ điều khiển (mà sẽ là theo yêu cầu) trong khi anh ta cần một singleton. Nói chung, chúng tôi muốn tiêm phụ thuộc, thay vì sử dụng các lớp/thuộc tính tĩnh. –

+1

Hơn nữa, nếu bạn đọc nhận xét của OP về câu trả lời của Ryan Byrne, rõ ràng là (có lẽ OP chưa biết) OP đang tìm kiếm một cơ chế DI, thay vì chỉ là biến toàn cầu được khởi tạo đúng. –

Các vấn đề liên quan