【发布时间】:2018-12-26 11:47:49
【问题描述】:
我对 ASP.Net Core、C#、OOP、Javascript ……基本上是我目前使用的所有东西都很陌生。过去几个月我一直在阅读和学习,以便开始一个新的开发项目。 总而言之,我正在稳步前进,但我遇到了 IMemoryCache 的问题,我无法真正理解(或者是 DI?)。
我正在使用 ASP.Net Core 2.0 和 VS2017。我有一个包含 2 个项目的解决方案,我的主要 ASP.Net Core MVC Web 应用程序和一个 .Net Core 2.0 类库。
在类库中,我添加了一个要在其中使用缓存的类,因此我将 IMemoryCache 添加到构造函数中。
为了实例化这个类,我有另一个构造函数调用函数GetModelGuidAsync。
public class MdsEntityCRUD
{
#region ClassConstruct
private readonly IMemoryCache _cache;
public MdsEntityCRUD(IMemoryCache cache)
{
_cache = cache;
}
public MdsEntityCRUD(ServiceClient client, string modelName, string entityName, string versionFlag)
{
this.client = client;
this.ModelId = Task.Run(async () => await GetModelGuidAsync(modelName)).Result;
this.EntityName = entityName;
mdsWS.Version ver = Task.Run(async () => await GetVersionByPolicyAsync(client, VersionPolicy.Flag, versionFlag, this.ModelId)).Result;
this.VersionId = ver.Identifier.Id;
}
public async Task<Guid> GetModelGuidAsync(string modelName)
{
Dictionary<string, Guid> modelNames;
if (!_cache.TryGetValue("ModelNames", out modelNames) || !modelNames.ContainsKey(modelName))
{
modelNames = await GetModelNamesAsync();
_cache.Set("ModelNames", modelNames, new MemoryCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60) }); // CFG
}
return modelNames[modelName];
}
我已将 services.AddMemoryCache(); 添加到我的 MVC 项目启动中的 ConfigureServices 中。
我正在使用第二个构造函数从我的 MVC 项目中的控制器调用该类。
在运行时,if (!_cache.TryGetValue-statement 出现错误。这些是 Exception Helper 和异常窗口中显示的详细信息:
System.AggregateException HResult=0x80131500 消息=一个或多个 发生错误。 (对象引用未设置为 对象。)来源=System.Private.CoreLib StackTrace:在 System.Threading.Tasks.Task.ThrowIfExceptional(布尔 includeTaskCanceledExceptions) 在 System.Threading.Tasks.Task`1.GetResultCore(布尔 waitCompletionNotification)在 mdXmdsWS.MdsEntityCRUD..ctor(ServiceClient 客户端,字符串模型名称, String entityName) 在 C:\Users..\MdsEntityCRUD.cs:line 59 at MDS_MVC_Proto2.Controllers.DataExplorerController.EntityDataSource(DataManagerRequest dmr) 在 C:\Users..\Controllers\DataExplorerController.cs:165 行
在 Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(对象 目标,对象 [] 参数)在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__12.MoveNext()内部异常 1:NullReferenceException:对象引用未设置为 一个对象的实例。
和来自 ($exception).InnerException
- InnerException {System.NullReferenceException:对象引用未设置为对象的实例。在 Microsoft.Extensions.Caching.Memory.CacheExtensions.TryGetValue[TItem](IMemoryCache 缓存、对象键、TItem& 值)在 mdXmdsWS.MdsEntityCRUD.d__18.MoveNext() 在 C:\Users..\MdsEntityCRUD.cs:第 84 行 --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 在 mdXmdsWS.MdsEntityCRUD.c__DisplayClass16_0.b__0>d.MoveNext() 在 C:\Users..\MdsEntityCRUD.cs:line 59} System.Exception {System.NullReferenceException}
我不知道为什么会出现错误: 是因为缓存在类库中而不是在MVC项目中吗? 是因为我试图在从构造函数执行的函数中使用缓存吗? 我是否缺少一些配置?
渴望了解我哪里出错了......
【问题讨论】:
-
你的第二个构造函数在你的构造函数中没有
IMemoryCache参数,所以它显然是空的。此外,您的第二个构造函数建议您在某处new-ing 您的类,因为它具有字符串参数(无法通过 .NET Cores 依赖注入解决 - 除非您使用的是第 3 方 DI/IoC 框架,例如 Autofac 等.) -
刚刚根据您的评论尝试了一些事情,但这是我迷路的原因有两个:1)从我读到的关于 DI 的内容中,我了解到只有 1 个包含“注入”的构造函数类,你不应该与其他参数混合? 2)当我将 IMemoryCache 作为参数添加到第二个构造函数时,我需要在实例化类时传递一个参数(你是对的,我是从我的控制器中新建类)但我似乎无法传递一个有效的参数,因为我无法创建一个 IMemoryCache 的 new 实例作为参数传递?
-
依赖注入无法使用魔法。 DI 所做的一切与您在
new-ing 上课时所做的相同。除了一些图书馆为你做这件事并将它传递给你的班级。当您new-ing 您的班级时,IoC/DI 框架将不会参与。它没有编译器魔法(如 async/await)。作为一个经验法则:永远不要在你想要注入的类型上调用new。当然也有一些例外(工厂)和非服务(模型、pocos 等) -
换句话说:当您调用
public MdsEntityCRUD(ServiceClient client, string modelName, string entityName, string versionFlag)构造函数时,MdsEntityCRUD(IMemoryCache cache)不会被调用。当您使用 DI/IoC 时,您必须在代码中一直使用它,即从控制器到服务再到另一个服务,再到提供者等。 -
至于评论的第二部分:当你必须
new你的班级,并传递IMemoryCache,你需要在你的控制器中注入IMemoryCache,然后将它传递给你的类作为参数
标签: c# caching asp.net-core dependency-injection