我有一个ASP.NET MVC 5应用程序,它使用LightInject作为DI容器,我有一个Service类,它位于我的VS解决方案中的另一个类库中。
My Solution
|____ASP.NET MVC Web App (async controller calls service method)
|____Service Class Library
|____InMemoryCacheService (Singleton)
此服务类是指我在Jon Skeet's preferred singleton pattern方法(简化版)之后创建的InMemoryCacheService
Singleton类:
public sealed class InMemoryCacheService
{
private static readonly InMemoryCacheService _singleton = new InMemoryCacheService();
// A private constructor to restrict the object creation from outside
static InMemoryCacheService()
{
}
private InMemoryCacheService()
{
Log.Info("New In Memory Cache Service instance created!");
}
public static InMemoryCacheService Instance
{
get
{
return _singleton;
}
}
public Dictionary<string, ConcurrentDictionary<string, Changeset>> ChangesetCacheDictionary
{
get { return _changesetCacheDictionary; }
set { _changesetCacheDictionary = value; }
}
public string GetChangesetCacheKey(string releaseWorkItemId)
{
return $"{releaseWorkItemId}_{CHANGESET_CACHE}";
}
public T GetOrSet<T>(string cacheKey, TimeSpan duration) where T : class
{
var item = MemoryCache.Default.Get(cacheKey) as T;
if (item == null)
{
lock (CacheLockObject)
{
item = GetItemFromCacheType<T>(cacheKey);
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.Add(duration));
}
}
return item;
}
private T GetItemFromCacheType<T>(string cacheKey) where T : class
{
T result = null;
var tokens = cacheKey.Split('_');
var releaseWorkItemId = tokens[0];
var cacheType = tokens[1];
switch (cacheType)
{
case CHANGESET_CACHE:
result = GetChangesetitItem<T>(releaseWorkItemId);
break;
}
return result;
}
private T GetChangesetitItem<T>(string releaseWorkItemId) where T : class
{
T result = null;
if (ChangesetCacheDictionary == null)
{
ChangesetCacheDictionary = new Dictionary<string, ConcurrentDictionary<string, Changeset>>()
{
{ releaseWorkItemId,new ConcurrentDictionary<string, Changeset>() }
};
}
else if (!ChangesetCacheDictionary.ContainsKey(releaseWorkItemId))
{
ChangesetCacheDictionary.Add(releaseWorkItemId, new ConcurrentDictionary<string, Changeset>());
}
result = ChangesetCacheDictionary[releaseWorkItemId] as T;
return result;
}
}
我遇到的问题是,在调试时我注意到正在创建我的Singleton类的多个实例!我的单例实例是从异步控制器方法引用来生成报告,该报告调用我的服务和服务使用单例并行异步任务。
我第一次运行报表时初始化Singleton并按预期填充缓存。但是我第二次或第三次运行报告时会创建一个新实例。当我在笔记本电脑中运行我的webapp时似乎没有发生这种情况,我只在沙箱服务器中看到它。什么可能是错的想法?我的理解是我的Singleton只会创建一次。
以下是我的服务如何使用Singleton InMemoryCacheService
:
GitCommitCache = InMemoryCacheService.Instance.GetOrSet<ConcurrentDictionary<string,GitCommit>>(gitCommitCacheKey,new TimeSpan(1, 0, 0, 0));