Fixes: U4-3505 Sometimes macro parameter types are not resolved during startup

This commit is contained in:
Shannon
2013-12-06 14:06:53 +11:00
parent 8327b8aa0e
commit dc7c7304ad
2 changed files with 50 additions and 10 deletions

View File

@@ -309,7 +309,7 @@ namespace Umbraco.Core
//return false but specify this exception type so we can detect it
if (typeElement == null)
return Attempt<IEnumerable<string>>.Fail(new CachedPluginNotFoundInFile());
return Attempt<IEnumerable<string>>.Fail(new CachedPluginNotFoundInFileException());
//return success
return Attempt.Succeed(typeElement.Elements("add")
@@ -671,8 +671,15 @@ namespace Umbraco.Core
{
//check if the TypeList already exists, if so return it, if not we'll create it
var typeList = _types.SingleOrDefault(x => x.IsTypeList<T>(resolutionType));
//need to put some logging here to try to figure out why this is happening: http://issues.umbraco.org/issue/U4-3505
if (cacheResult && typeList != null)
{
LogHelper.Debug<PluginManager>("Existing typeList found for {0} with resolution type {1}", () => typeof(T), () => resolutionType);
}
//if we're not caching the result then proceed, or if the type list doesn't exist then proceed
if (!cacheResult || typeList == null)
if (cacheResult == false || typeList == null)
{
//upgrade to a write lock since we're adding to the collection
readLock.UpgradeToWriteLock();
@@ -681,15 +688,17 @@ namespace Umbraco.Core
//we first need to look into our cache file (this has nothing to do with the 'cacheResult' parameter which caches in memory).
//if assemblies have not changed and the cache file actually exists, then proceed to try to lookup by the cache file.
if (!HaveAssembliesChanged && File.Exists(GetPluginListFilePath()))
if (HaveAssembliesChanged == false && File.Exists(GetPluginListFilePath()))
{
var fileCacheResult = TryGetCachedPluginsFromFile<T>(resolutionType);
//here we need to identify if the CachedPluginNotFoundInFile was the exception, if it was then we need to re-scan
//in some cases the plugin will not have been scanned for on application startup, but the assemblies haven't changed
//so in this instance there will never be a result.
if (fileCacheResult.Exception != null && fileCacheResult.Exception is CachedPluginNotFoundInFile)
if (fileCacheResult.Exception != null && fileCacheResult.Exception is CachedPluginNotFoundInFileException)
{
LogHelper.Debug<PluginManager>("Tried to find typelist for type {0} and resolution {1} in file cache but the type was not found so loading types by assembly scan ", () => typeof(T), () => resolutionType);
//we don't have a cache for this so proceed to look them up by scanning
LoadViaScanningAndUpdateCacheFile<T>(typeList, resolutionType, finder);
}
@@ -717,20 +726,22 @@ namespace Umbraco.Core
break;
}
}
if (!successfullyLoadedFromCache)
if (successfullyLoadedFromCache == false)
{
//we need to manually load by scanning if loading from the file was not successful.
LoadViaScanningAndUpdateCacheFile<T>(typeList, resolutionType, finder);
}
else
{
LogHelper.Debug<PluginManager>("Loaded plugin types " + typeof(T).FullName + " from persisted cache");
LogHelper.Debug<PluginManager>("Loaded plugin types {0} with resolution {1} from persisted cache", () => typeof(T), () => resolutionType);
}
}
}
}
else
{
LogHelper.Debug<PluginManager>("Assembly changes detected, loading types {0} for resolution {1} by assembly scan", () => typeof(T), () => resolutionType);
//we don't have a cache for this so proceed to look them up by scanning
LoadViaScanningAndUpdateCacheFile<T>(typeList, resolutionType, finder);
}
@@ -739,7 +750,10 @@ namespace Umbraco.Core
if (cacheResult)
{
//add the type list to the collection
_types.Add(typeList);
var added = _types.Add(typeList);
LogHelper.Debug<PluginManager>("Caching of typelist for type {0} and resolution {1} was successful = {2}", () => typeof(T), () => resolutionType, () => added);
}
}
typesFound = typeList.GetTypes().ToList();
@@ -863,14 +877,14 @@ namespace Umbraco.Core
}
/// <summary>
/// Returns true if the current TypeList is of the same type and of the same type
/// Returns true if the current TypeList is of the same lookup type
/// </summary>
/// <typeparam name="TLookup"></typeparam>
/// <param name="resolutionType"></param>
/// <returns></returns>
public override bool IsTypeList<TLookup>(TypeResolutionKind resolutionType)
{
return _resolutionType == resolutionType && (typeof(T)).IsType<TLookup>();
return _resolutionType == resolutionType && (typeof(T)) == typeof(TLookup);
}
public override IEnumerable<Type> GetTypes()
@@ -883,7 +897,7 @@ namespace Umbraco.Core
/// This class is used simply to determine that a plugin was not found in the cache plugin list with the specified
/// TypeResolutionKind.
/// </summary>
internal class CachedPluginNotFoundInFile : Exception
internal class CachedPluginNotFoundInFileException : Exception
{
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
@@ -9,8 +10,10 @@ using NUnit.Framework;
using SqlCE4Umbraco;
using Umbraco.Core;
using Umbraco.Core.IO;
using Umbraco.Core.PropertyEditors;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.PropertyEditors;
using umbraco;
using umbraco.DataLayer;
using umbraco.MacroEngines;
@@ -333,6 +336,29 @@ namespace Umbraco.Tests
var types = PluginManager.Current.ResolveXsltExtensions();
Assert.AreEqual(3, types.Count());
}
/// <summary>
/// This demonstrates this issue: http://issues.umbraco.org/issue/U4-3505 - the TypeList was returning a list of assignable types
/// not explicit types which is sort of ideal but is confusing so we'll do it the less confusing way.
/// </summary>
[Test]
public void TypeList_Resolves_Explicit_Types()
{
var types = new HashSet<PluginManager.TypeList>();
var propEditors = new PluginManager.TypeList<PropertyEditor>(PluginManager.TypeResolutionKind.FindAllTypes);
propEditors.AddType(typeof (LabelPropertyEditor));
types.Add(propEditors);
var found = types.SingleOrDefault(x => x.IsTypeList<PropertyEditor>(PluginManager.TypeResolutionKind.FindAllTypes));
Assert.IsNotNull(found);
//This should not find a type list of this type
var shouldNotFind = types.SingleOrDefault(x => x.IsTypeList<IParameterEditor>(PluginManager.TypeResolutionKind.FindAllTypes));
Assert.IsNull(shouldNotFind);
}
[XsltExtension("Blah.Blah")]
public class MyXsltExtension