Myślę, że lepszym rozwiązaniem byłoby użycie Ninject
lub innej struktury wtrysku zależności, aby wprowadzić w razie potrzeby swój MemoryCache
do kontrolerów.
Zaczniesz od dodania Ninject
i Ninject.Mvc3
(i innych powiązanych bitów) do projektu ASP.NET MVC. Jeśli pracujesz w Visual Studio, możesz użyć NuGet, aby to zrobić. Jest dość bezbolesny i dobrze zautomatyzowany.
Następnym krokiem będzie owinąć MemoryCache
do pewnego rodzaju interfejsu, takich jak:
public interface IMemoryCacheService
{
MemoryCache MemoryCache
{
get;
set;
}
}
oraz:
public class MemoryCacheService : IMemoryCacheService
{
public MemoryCacheService()
{
MemoryCache = new MemoryCache();
}
public MemoryCache MemoryCache
{
get;
set;
}
}
Następnie należy zdefiniować wiązania wewnątrz Ninject tak że Ninject wie że gdy potrzebujesz czegoś typu IMemoryCacheService
, powinieneś podać instancję MemoryCacheService
.
Wkleję tutaj własną klasę konfiguracyjną Ninject. Ten, który zostanie utworzony w twoim projekcie, będzie bardzo podobny i znajdzie się w folderze o nazwie App_Start
(który zostanie utworzony automatycznie, jeśli użyjesz NuGet). Klasa domyślnie tworzona przez program Ninject nosi nazwę 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>();
}
}
Wreszcie kontrolery zmieni się z:
public class HomeController : Controller
{
public ActionResult Foo()
{
...
}
...
}
do:
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, dokonane innej usługi, jak również o nazwie IEmailService
po wyżej wymienionej strategii, a ty chciał IEmailService
być również dostępny w HomeController
, a następnie:
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 zmieni fabrykę kontrolera ASP.NET MVC, aby automatycznie podawać wstrzyknięte argumenty do konstruktorów kontrolera.
Myślę, że ten rodzaj podejścia jest lepsze na dłuższą metę, że utrzymanie zmiennych globalnych itp
Sprawdź to http://www.deanhume.com/home/blogpost/object-caching----net -4/37 – Mate