我们有一个旧版CMS系统,该问题似乎更经常发生(可能是由于.NET v4升级并以64位运行)。
(由于机密性,我不得不删除对CMS名称的所有引用)
以下是我们实时服务器中转储文件的摘要。
./src/index.js
这最终也导致我们使用Utils.GetMethodsWithAttribute(DetectServicePage使用的)
背景:如果所请求的页面是“服务页面”而不是常规内容页面,则调用DetectServicePage方法以解决此问题
System.Collections.Generic.Dictionary`2[[InternalCMSNameRedacted.Core.Utils+MethodWithAttributeKey, InternalCMSNameRedacted.Core],[System.__Canon, mscorlib]].FindEntry(MethodWithAttributeKey)+f5
System.Collections.Generic.Dictionary`2[[InternalCMSNameRedacted.Core.Utils+MethodWithAttributeKey, InternalCMSNameRedacted.Core],[System.__Canon, mscorlib]].TryGetValue(MethodWithAttributeKey, System.__Canon ByRef)+14
InternalCMSNameRedacted.Core.ConcurrentMap`2[[InternalCMSNameRedacted.Core.Utils+MethodWithAttributeKey, InternalCMSNameRedacted.Core],[System.__Canon, mscorlib]].TryGetValue( MethodWithAttributeKey, System.__Canon ByRef)+8d
InternalCMSNameRedacted.Core.Utils.GetMethodsWithAttribute[[System.__Canon, mscorlib],[System.__Canon, mscorlib]]()+1f9
InternalCMSNameRedacted.Core.InternalCMSNameRedactedHandler.DetectServicePage(InternalCMSNameRedacted.Core.ServicePageData)+39c
这将调用Utils.GetMethodsWithAttribute,我认为这是问题所在(基于转储文件)。以下是此方法的代码:
foreach (MethodInfo mi in Utils.GetMethodsWithAttribute<ServicePageHandlerAttribute, ServicePageHandlerContainerAttribute>())
{
foreach (ServicePageHandlerAttribute spha in mi.GetCustomAttributes<ServicePageHandlerAttribute>())
{
if (urlParts[0] == spha.ServicePage)
{
if (data.IsPasswordProtection)
{
if (mi.ReturnType == typeof(ServicePageData))
{
return mi.Invoke(null, new object[] { data }) as ServicePageData;
}
else
{
continue;
}
}
else
{
if (mi.ReturnType == typeof(ServicePageData))
{
return mi.Invoke(null, new object[] { data }) as ServicePageData;
}
else
{
mi.Invoke(null, new object[] { });
}
}
if (spha.EndResponse)
{
Oracle.Response.End();
}
}
}
}
这使用了CMS特定的数据存储ConcurrentMap:
private readonly static ConcurrentMap<MethodWithAttributeKey, ICollection<MethodInfo>> _MethodsWithAttributeCache = new ConcurrentMap<MethodWithAttributeKey, ICollection<MethodInfo>>();
private readonly static ConcurrentMap<MethodWithAttributeKey, ICollection<string>> _ClassesWithAttributeStringCache = new ConcurrentMap<MethodWithAttributeKey, ICollection<string>>();
public static ICollection<MethodInfo> GetMethodsWithAttribute<AttributeType, ContainerAttributeType>()
where AttributeType : Attribute
where ContainerAttributeType : Attribute
{
List<Type> validTypes = null;
List<MethodInfo> l = new List<MethodInfo>();
var key = new MethodWithAttributeKey {
AttributeType = typeof(AttributeType),
ContainerAttributeType = typeof(ContainerAttributeType)
};
ICollection<MethodInfo> methods;
if (_MethodsWithAttributeCache.TryGetValue(key, out methods)) {
// If the methods are in the cache and none have disappeared
if (methods != null && methods.None(m => m == null)) {
return methods;
}
// At least one of the methods we cached last time do not appear to exist now
// so we need to regenerate from the classesWithAttributeStringCache if possible
if (_ClassesWithAttributeStringCache.ContainsKey(key))
{
validTypes = new List<Type>();
foreach (var ts in _ClassesWithAttributeStringCache[key])
{
Type type = BuildManager.GetType(ts, false, true);
if (type != null) {
validTypes.Add(type);
}
}
}
}
if (validTypes == null) {
validTypes = new List<Type>();
foreach (Assembly assembly in Thread.GetDomain().GetAssemblies().Where(a => !a.FullName.StartsWith("System."))) {
Type[] assemblyTypes = null;
try {
assemblyTypes = assembly.GetTypes();
}
catch (ReflectionTypeLoadException refEx) {
EventLog.Add(refEx);
refEx.LoaderExceptions.ToList().ForEach(e => EventLog.Add(e));
//throw refEx;
continue;
}
catch (Exception ex)
{
EventLog.Add(ex);
continue;
}
if (assemblyTypes != null)
{
foreach (var t in assemblyTypes)
{
if (t.GetCustomAttributes<ContainerAttributeType>().Count > 0)
{
validTypes.Add(t);
}
}
}
}
List<string> typeStrings = new List<string>();
validTypes.ToList().ForEach(t => typeStrings.Add(t.AssemblyQualifiedName));
_ClassesWithAttributeStringCache[key] = typeStrings;
}
foreach (Type currentType in validTypes) {
foreach (var m in currentType.GetMethods()) {
if (m.GetCustomAttributes<AttributeType>().Count > 0) {
l.Add(m);
}
}
}
// Add into
_MethodsWithAttributeCache[key] = l;
return l;
}
我感觉这是自定义实现-并发映射,可能有一个我们可以使用的本机实现,因为它是在.net v2中构建的