Namespace and file cleanup - Profiling --> Logging, root cache stuff moved to Cache, XmlHelper --> Xml, TypeFinder, etc.. --> Plugins

This commit is contained in:
Shannon
2016-05-18 23:34:56 +02:00
parent 7fb1b4fb3b
commit 8127731f72
158 changed files with 3549 additions and 3483 deletions

View File

@@ -1,6 +1,7 @@
using System;
using System.Configuration;
using System.Threading;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;

View File

@@ -1,428 +1,421 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Caching;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
namespace Umbraco.Core
{
/// <summary>
/// Class that is exposed by the ApplicationContext for application wide caching purposes
/// </summary>
public class CacheHelper
{
private static readonly ICacheProvider NullRequestCache = new NullCacheProvider();
private static readonly ICacheProvider NullStaticCache = new NullCacheProvider();
private static readonly IRuntimeCacheProvider NullRuntimeCache = new NullCacheProvider();
/// <summary>
/// Creates a cache helper with disabled caches
/// </summary>
/// <returns></returns>
/// <remarks>
/// Good for unit testing
/// </remarks>
public static CacheHelper CreateDisabledCacheHelper()
{
return new CacheHelper(NullRuntimeCache, NullStaticCache, NullRequestCache, new IsolatedRuntimeCache(t => NullRuntimeCache));
}
/// <summary>
/// Initializes a new instance for use in the web
/// </summary>
public CacheHelper()
: this(
new HttpRuntimeCacheProvider(HttpRuntime.Cache),
new StaticCacheProvider(),
new HttpRequestCacheProvider(),
new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider()))
{
}
/// <summary>
/// Initializes a new instance for use in the web
/// </summary>
/// <param name="cache"></param>
public CacheHelper(System.Web.Caching.Cache cache)
: this(
new HttpRuntimeCacheProvider(cache),
new StaticCacheProvider(),
new HttpRequestCacheProvider(),
new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider()))
{
}
[Obsolete("Use the constructor the specifies all dependencies")]
[EditorBrowsable(EditorBrowsableState.Never)]
public CacheHelper(
IRuntimeCacheProvider httpCacheProvider,
ICacheProvider staticCacheProvider,
ICacheProvider requestCacheProvider)
: this(httpCacheProvider, staticCacheProvider, requestCacheProvider, new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider()))
{
}
/// <summary>
/// Initializes a new instance based on the provided providers
/// </summary>
/// <param name="httpCacheProvider"></param>
/// <param name="staticCacheProvider"></param>
/// <param name="requestCacheProvider"></param>
/// <param name="isolatedCacheManager"></param>
public CacheHelper(
IRuntimeCacheProvider httpCacheProvider,
ICacheProvider staticCacheProvider,
ICacheProvider requestCacheProvider,
IsolatedRuntimeCache isolatedCacheManager)
{
if (httpCacheProvider == null) throw new ArgumentNullException("httpCacheProvider");
if (staticCacheProvider == null) throw new ArgumentNullException("staticCacheProvider");
if (requestCacheProvider == null) throw new ArgumentNullException("requestCacheProvider");
if (isolatedCacheManager == null) throw new ArgumentNullException("isolatedCacheManager");
RuntimeCache = httpCacheProvider;
StaticCache = staticCacheProvider;
RequestCache = requestCacheProvider;
IsolatedRuntimeCache = isolatedCacheManager;
}
/// <summary>
/// Returns the current Request cache
/// </summary>
public ICacheProvider RequestCache { get; internal set; }
/// <summary>
/// Returns the current Runtime cache
/// </summary>
public ICacheProvider StaticCache { get; internal set; }
/// <summary>
/// Returns the current Runtime cache
/// </summary>
public IRuntimeCacheProvider RuntimeCache { get; internal set; }
/// <summary>
/// Returns the current Isolated Runtime cache manager
/// </summary>
public IsolatedRuntimeCache IsolatedRuntimeCache { get; internal set; }
#region Legacy Runtime/Http Cache accessors
/// <summary>
/// Clears the item in umbraco's runtime cache
/// </summary>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearAllCache()
{
RuntimeCache.ClearAllCache();
IsolatedRuntimeCache.ClearAllCaches();
}
/// <summary>
/// Clears the item in umbraco's runtime cache with the given key
/// </summary>
/// <param name="key">Key</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheItem(string key)
{
RuntimeCache.ClearCacheItem(key);
}
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type name as the
/// input parameter. (using [object].GetType())
/// </summary>
/// <param name="typeName">The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument"</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearCacheObjectTypes(string typeName)
{
RuntimeCache.ClearCacheObjectTypes(typeName);
}
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type specified
/// </summary>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheObjectTypes<T>()
{
RuntimeCache.ClearCacheObjectTypes<T>();
}
/// <summary>
/// Clears all cache items that starts with the key passed.
/// </summary>
/// <param name="keyStartsWith">The start of the key</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheByKeySearch(string keyStartsWith)
{
RuntimeCache.ClearCacheByKeySearch(keyStartsWith);
}
/// <summary>
/// Clears all cache items that have a key that matches the regular expression
/// </summary>
/// <param name="regexString"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheByKeyExpression(string regexString)
{
RuntimeCache.ClearCacheByKeyExpression(regexString);
}
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
{
return RuntimeCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
}
/// <summary>
/// Returns a cache item by key, does not update the cache if it isn't there.
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with all of the default parameters
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey, Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey,
TimeSpan timeout, Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="refreshAction"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemRemovedCallback refreshAction, TimeSpan timeout,
Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, removedCallback: refreshAction);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout,
Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, false, priority, refreshAction);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<TT> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
return result == null ? default(TT) : result.TryConvertTo<TT>().Result;
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="cacheDependency"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
Func<TT> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), null, false, priority, null, cacheDependency);
return result == null ? default(TT) : result.TryConvertTo<TT>().Result;
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
Func<T> getCacheItem)
{
RuntimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, priority: priority);
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
TimeSpan timeout,
Func<T> getCacheItem)
{
RuntimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, timeout, priority: priority);
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<T> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, null, cacheDependency);
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan? timeout,
Func<T> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
#endregion
private HttpRuntimeCacheProvider GetHttpRuntimeCacheProvider(IRuntimeCacheProvider runtimeCache)
{
HttpRuntimeCacheProvider cache;
var wrapper = RuntimeCache as IRuntimeCacheProviderWrapper;
if (wrapper != null)
{
cache = wrapper.InnerProvider as HttpRuntimeCacheProvider;
}
else
{
cache = RuntimeCache as HttpRuntimeCacheProvider;
}
return cache;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web;
using System.Web.Caching;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Class that is exposed by the ApplicationContext for application wide caching purposes
/// </summary>
public class CacheHelper
{
private static readonly ICacheProvider NullRequestCache = new NullCacheProvider();
private static readonly ICacheProvider NullStaticCache = new NullCacheProvider();
private static readonly IRuntimeCacheProvider NullRuntimeCache = new NullCacheProvider();
/// <summary>
/// Creates a cache helper with disabled caches
/// </summary>
/// <returns></returns>
/// <remarks>
/// Good for unit testing
/// </remarks>
public static CacheHelper CreateDisabledCacheHelper()
{
return new CacheHelper(NullRuntimeCache, NullStaticCache, NullRequestCache, new IsolatedRuntimeCache(t => NullRuntimeCache));
}
/// <summary>
/// Initializes a new instance for use in the web
/// </summary>
public CacheHelper()
: this(
new HttpRuntimeCacheProvider(HttpRuntime.Cache),
new StaticCacheProvider(),
new HttpRequestCacheProvider(),
new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider()))
{
}
/// <summary>
/// Initializes a new instance for use in the web
/// </summary>
/// <param name="cache"></param>
public CacheHelper(System.Web.Caching.Cache cache)
: this(
new HttpRuntimeCacheProvider(cache),
new StaticCacheProvider(),
new HttpRequestCacheProvider(),
new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider()))
{
}
[Obsolete("Use the constructor the specifies all dependencies")]
[EditorBrowsable(EditorBrowsableState.Never)]
public CacheHelper(
IRuntimeCacheProvider httpCacheProvider,
ICacheProvider staticCacheProvider,
ICacheProvider requestCacheProvider)
: this(httpCacheProvider, staticCacheProvider, requestCacheProvider, new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider()))
{
}
/// <summary>
/// Initializes a new instance based on the provided providers
/// </summary>
/// <param name="httpCacheProvider"></param>
/// <param name="staticCacheProvider"></param>
/// <param name="requestCacheProvider"></param>
/// <param name="isolatedCacheManager"></param>
public CacheHelper(
IRuntimeCacheProvider httpCacheProvider,
ICacheProvider staticCacheProvider,
ICacheProvider requestCacheProvider,
IsolatedRuntimeCache isolatedCacheManager)
{
if (httpCacheProvider == null) throw new ArgumentNullException("httpCacheProvider");
if (staticCacheProvider == null) throw new ArgumentNullException("staticCacheProvider");
if (requestCacheProvider == null) throw new ArgumentNullException("requestCacheProvider");
if (isolatedCacheManager == null) throw new ArgumentNullException("isolatedCacheManager");
RuntimeCache = httpCacheProvider;
StaticCache = staticCacheProvider;
RequestCache = requestCacheProvider;
IsolatedRuntimeCache = isolatedCacheManager;
}
/// <summary>
/// Returns the current Request cache
/// </summary>
public ICacheProvider RequestCache { get; internal set; }
/// <summary>
/// Returns the current Runtime cache
/// </summary>
public ICacheProvider StaticCache { get; internal set; }
/// <summary>
/// Returns the current Runtime cache
/// </summary>
public IRuntimeCacheProvider RuntimeCache { get; internal set; }
/// <summary>
/// Returns the current Isolated Runtime cache manager
/// </summary>
public IsolatedRuntimeCache IsolatedRuntimeCache { get; internal set; }
#region Legacy Runtime/Http Cache accessors
/// <summary>
/// Clears the item in umbraco's runtime cache
/// </summary>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearAllCache()
{
RuntimeCache.ClearAllCache();
IsolatedRuntimeCache.ClearAllCaches();
}
/// <summary>
/// Clears the item in umbraco's runtime cache with the given key
/// </summary>
/// <param name="key">Key</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheItem(string key)
{
RuntimeCache.ClearCacheItem(key);
}
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type name as the
/// input parameter. (using [object].GetType())
/// </summary>
/// <param name="typeName">The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument"</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearCacheObjectTypes(string typeName)
{
RuntimeCache.ClearCacheObjectTypes(typeName);
}
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type specified
/// </summary>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheObjectTypes<T>()
{
RuntimeCache.ClearCacheObjectTypes<T>();
}
/// <summary>
/// Clears all cache items that starts with the key passed.
/// </summary>
/// <param name="keyStartsWith">The start of the key</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheByKeySearch(string keyStartsWith)
{
RuntimeCache.ClearCacheByKeySearch(keyStartsWith);
}
/// <summary>
/// Clears all cache items that have a key that matches the regular expression
/// </summary>
/// <param name="regexString"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheByKeyExpression(string regexString)
{
RuntimeCache.ClearCacheByKeyExpression(regexString);
}
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
{
return RuntimeCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
}
/// <summary>
/// Returns a cache item by key, does not update the cache if it isn't there.
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with all of the default parameters
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey, Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey,
TimeSpan timeout, Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="refreshAction"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemRemovedCallback refreshAction, TimeSpan timeout,
Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, removedCallback: refreshAction);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout,
Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, false, priority, refreshAction);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<TT> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
return result == null ? default(TT) : result.TryConvertTo<TT>().Result;
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="cacheDependency"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
Func<TT> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), null, false, priority, null, cacheDependency);
return result == null ? default(TT) : result.TryConvertTo<TT>().Result;
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
Func<T> getCacheItem)
{
RuntimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, priority: priority);
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
TimeSpan timeout,
Func<T> getCacheItem)
{
RuntimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, timeout, priority: priority);
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<T> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, null, cacheDependency);
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan? timeout,
Func<T> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
#endregion
private HttpRuntimeCacheProvider GetHttpRuntimeCacheProvider(IRuntimeCacheProvider runtimeCache)
{
HttpRuntimeCacheProvider cache;
var wrapper = RuntimeCache as IRuntimeCacheProviderWrapper;
if (wrapper != null)
{
cache = wrapper.InnerProvider as HttpRuntimeCacheProvider;
}
else
{
cache = RuntimeCache as HttpRuntimeCacheProvider;
}
return cache;
}
}
}

View File

@@ -1,46 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using LightInject;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Cache;
namespace Umbraco.Core
{
/// <summary>
/// A resolver to return all ICacheRefresher objects
/// </summary>
internal sealed class CacheRefreshersResolver : ContainerLazyManyObjectsResolver<CacheRefreshersResolver, ICacheRefresher>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="serviceContainer"></param>
/// <param name="logger"></param>
/// <param name="refreshers"></param>
internal CacheRefreshersResolver(IServiceContainer serviceContainer, ILogger logger, Func<IEnumerable<Type>> refreshers)
: base(serviceContainer, logger, refreshers)
{
}
/// <summary>
/// Gets the <see cref="ICacheRefresher"/> implementations.
/// </summary>
public IEnumerable<ICacheRefresher> CacheRefreshers => Values;
/// <summary>
/// Returns an instance for the type identified by its unique type identifier.
/// </summary>
/// <param name="id">The type identifier.</param>
/// <returns>The value of the type uniquely identified by <paramref name="id"/>.</returns>
public ICacheRefresher GetById(Guid id)
{
return Values.FirstOrDefault(x => x.UniqueIdentifier == id);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using LightInject;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Core.Cache
{
/// <summary>
/// A resolver to return all ICacheRefresher objects
/// </summary>
internal sealed class CacheRefreshersResolver : ContainerLazyManyObjectsResolver<CacheRefreshersResolver, ICacheRefresher>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="serviceContainer"></param>
/// <param name="logger"></param>
/// <param name="refreshers"></param>
internal CacheRefreshersResolver(IServiceContainer serviceContainer, ILogger logger, Func<IEnumerable<Type>> refreshers)
: base(serviceContainer, logger, refreshers)
{
}
/// <summary>
/// Gets the <see cref="ICacheRefresher"/> implementations.
/// </summary>
public IEnumerable<ICacheRefresher> CacheRefreshers => Values;
/// <summary>
/// Returns an instance for the type identified by its unique type identifier.
/// </summary>
/// <param name="id">The type identifier.</param>
/// <returns>The value of the type uniquely identified by <paramref name="id"/>.</returns>
public ICacheRefresher GetById(Guid id)
{
return Values.FirstOrDefault(x => x.UniqueIdentifier == id);
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Umbraco.Core.Plugins;
namespace Umbraco.Core.Cache
{

View File

@@ -8,6 +8,7 @@ using System.Text.RegularExpressions;
using System.Threading;
using System.Web.Caching;
using Umbraco.Core.Logging;
using Umbraco.Core.Plugins;
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
namespace Umbraco.Core.Cache

View File

@@ -1,167 +1,167 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace Umbraco.Core
{
/// <summary>
/// A thread-safe representation of a <see cref="HashSet{T}"/>.
/// Enumerating this collection is thread-safe and will only operate on a clone that is generated before returning the enumerator.
/// </summary>
/// <typeparam name="T"></typeparam>
[Serializable]
public class ConcurrentHashSet<T> : ICollection<T>
{
private readonly HashSet<T> _innerSet = new HashSet<T>();
private readonly ReaderWriterLockSlim _instanceLocker = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<T> GetEnumerator()
{
return GetThreadSafeClone().GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <returns>
/// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </returns>
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public bool Remove(T item)
{
using (new WriteLock(_instanceLocker))
{
return _innerSet.Remove(item);
}
}
/// <summary>
/// Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
/// </summary>
/// <returns>
/// The number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
public int Count
{
get { return GetThreadSafeClone().Count; }
}
/// <summary>
/// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
/// </summary>
/// <returns>
/// true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false.
/// </returns>
public bool IsReadOnly
{
get { return false; }
}
/// <summary>
/// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public void Add(T item)
{
using (new WriteLock(_instanceLocker))
{
_innerSet.Add(item);
}
}
/// <summary>
/// Attempts to add an item to the collection
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool TryAdd(T item)
{
var clone = GetThreadSafeClone();
if (clone.Contains(item)) return false;
using (new WriteLock(_instanceLocker))
{
//double check
if (_innerSet.Contains(item)) return false;
_innerSet.Add(item);
return true;
}
}
/// <summary>
/// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
public void Clear()
{
using (new WriteLock(_instanceLocker))
{
_innerSet.Clear();
}
}
/// <summary>
/// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
/// </summary>
/// <returns>
/// true if <paramref name="item"/> is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false.
/// </returns>
/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
public bool Contains(T item)
{
return GetThreadSafeClone().Contains(item);
}
/// <summary>
/// Copies the elements of the <see cref="T:System.Collections.Concurrent.IProducerConsumerCollection`1"/> to an <see cref="T:System.Array"/>, starting at a specified index.
/// </summary>
/// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from the <see cref="T:System.Collections.Concurrent.IProducerConsumerCollection`1"/>. The array must have zero-based indexing.</param><param name="index">The zero-based index in <paramref name="array"/> at which copying begins.</param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in Visual Basic).</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is less than zero.</exception><exception cref="T:System.ArgumentException"><paramref name="index"/> is equal to or greater than the length of the <paramref name="array"/> -or- The number of elements in the source <see cref="T:System.Collections.Concurrent.ConcurrentQueue`1"/> is greater than the available space from <paramref name="index"/> to the end of the destination <paramref name="array"/>.</exception>
public void CopyTo(T[] array, int index)
{
var clone = GetThreadSafeClone();
clone.CopyTo(array, index);
}
private HashSet<T> GetThreadSafeClone()
{
HashSet<T> clone = null;
using (new WriteLock(_instanceLocker))
{
clone = new HashSet<T>(_innerSet, _innerSet.Comparer);
}
return clone;
}
/// <summary>
/// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
/// </summary>
/// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:System.Collections.ICollection"/>. The <see cref="T:System.Array"/> must have zero-based indexing. </param><param name="index">The zero-based index in <paramref name="array"/> at which copying begins. </param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null. </exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is less than zero. </exception><exception cref="T:System.ArgumentException"><paramref name="array"/> is multidimensional.-or- The number of elements in the source <see cref="T:System.Collections.ICollection"/> is greater than the available space from <paramref name="index"/> to the end of the destination <paramref name="array"/>. </exception><exception cref="T:System.ArgumentException">The type of the source <see cref="T:System.Collections.ICollection"/> cannot be cast automatically to the type of the destination <paramref name="array"/>. </exception><filterpriority>2</filterpriority>
public void CopyTo(Array array, int index)
{
var clone = GetThreadSafeClone();
Array.Copy(clone.ToArray(), 0, array, index, clone.Count);
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace Umbraco.Core.Collections
{
/// <summary>
/// A thread-safe representation of a <see cref="HashSet{T}"/>.
/// Enumerating this collection is thread-safe and will only operate on a clone that is generated before returning the enumerator.
/// </summary>
/// <typeparam name="T"></typeparam>
[Serializable]
public class ConcurrentHashSet<T> : ICollection<T>
{
private readonly HashSet<T> _innerSet = new HashSet<T>();
private readonly ReaderWriterLockSlim _instanceLocker = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<T> GetEnumerator()
{
return GetThreadSafeClone().GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <returns>
/// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </returns>
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public bool Remove(T item)
{
using (new WriteLock(_instanceLocker))
{
return _innerSet.Remove(item);
}
}
/// <summary>
/// Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
/// </summary>
/// <returns>
/// The number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
public int Count
{
get { return GetThreadSafeClone().Count; }
}
/// <summary>
/// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
/// </summary>
/// <returns>
/// true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false.
/// </returns>
public bool IsReadOnly
{
get { return false; }
}
/// <summary>
/// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public void Add(T item)
{
using (new WriteLock(_instanceLocker))
{
_innerSet.Add(item);
}
}
/// <summary>
/// Attempts to add an item to the collection
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool TryAdd(T item)
{
var clone = GetThreadSafeClone();
if (clone.Contains(item)) return false;
using (new WriteLock(_instanceLocker))
{
//double check
if (_innerSet.Contains(item)) return false;
_innerSet.Add(item);
return true;
}
}
/// <summary>
/// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
public void Clear()
{
using (new WriteLock(_instanceLocker))
{
_innerSet.Clear();
}
}
/// <summary>
/// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
/// </summary>
/// <returns>
/// true if <paramref name="item"/> is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false.
/// </returns>
/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
public bool Contains(T item)
{
return GetThreadSafeClone().Contains(item);
}
/// <summary>
/// Copies the elements of the <see cref="T:System.Collections.Concurrent.IProducerConsumerCollection`1"/> to an <see cref="T:System.Array"/>, starting at a specified index.
/// </summary>
/// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from the <see cref="T:System.Collections.Concurrent.IProducerConsumerCollection`1"/>. The array must have zero-based indexing.</param><param name="index">The zero-based index in <paramref name="array"/> at which copying begins.</param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in Visual Basic).</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is less than zero.</exception><exception cref="T:System.ArgumentException"><paramref name="index"/> is equal to or greater than the length of the <paramref name="array"/> -or- The number of elements in the source <see cref="T:System.Collections.Concurrent.ConcurrentQueue`1"/> is greater than the available space from <paramref name="index"/> to the end of the destination <paramref name="array"/>.</exception>
public void CopyTo(T[] array, int index)
{
var clone = GetThreadSafeClone();
clone.CopyTo(array, index);
}
private HashSet<T> GetThreadSafeClone()
{
HashSet<T> clone = null;
using (new WriteLock(_instanceLocker))
{
clone = new HashSet<T>(_innerSet, _innerSet.Comparer);
}
return clone;
}
/// <summary>
/// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
/// </summary>
/// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:System.Collections.ICollection"/>. The <see cref="T:System.Array"/> must have zero-based indexing. </param><param name="index">The zero-based index in <paramref name="array"/> at which copying begins. </param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null. </exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is less than zero. </exception><exception cref="T:System.ArgumentException"><paramref name="array"/> is multidimensional.-or- The number of elements in the source <see cref="T:System.Collections.ICollection"/> is greater than the available space from <paramref name="index"/> to the end of the destination <paramref name="array"/>. </exception><exception cref="T:System.ArgumentException">The type of the source <see cref="T:System.Collections.ICollection"/> cannot be cast automatically to the type of the destination <paramref name="array"/>. </exception><filterpriority>2</filterpriority>
public void CopyTo(Array array, int index)
{
var clone = GetThreadSafeClone();
Array.Copy(clone.ToArray(), 0, array, index, clone.Count);
}
}
}

View File

@@ -1,172 +1,170 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Core
{
/// <summary>
/// An ObservableDictionary
/// </summary>
/// <remarks>
/// Assumes that the key will not change and is unique for each element in the collection.
/// Collection is not thread-safe, so calls should be made single-threaded.
/// </remarks>
/// <typeparam name="TValue">The type of elements contained in the BindableCollection</typeparam>
/// <typeparam name="TKey">The type of the indexing key</typeparam>
public class ObservableDictionary<TKey, TValue> : ObservableCollection<TValue>
{
protected Dictionary<TKey, int> Indecies = new Dictionary<TKey, int>();
protected Func<TValue, TKey> KeySelector;
/// <summary>
/// Create new ObservableDictionary
/// </summary>
/// <param name="keySelector">Selector function to create key from value</param>
public ObservableDictionary(Func<TValue, TKey> keySelector)
: base()
{
if (keySelector == null) throw new ArgumentException("keySelector");
KeySelector = keySelector;
}
#region Protected Methods
protected override void InsertItem(int index, TValue item)
{
var key = KeySelector(item);
if (Indecies.ContainsKey(key))
throw new DuplicateKeyException(key.ToString());
if (index != this.Count)
{
foreach (var k in Indecies.Keys.Where(k => Indecies[k] >= index).ToList())
{
Indecies[k]++;
}
}
base.InsertItem(index, item);
Indecies[key] = index;
}
protected override void ClearItems()
{
base.ClearItems();
Indecies.Clear();
}
protected override void RemoveItem(int index)
{
var item = this[index];
var key = KeySelector(item);
base.RemoveItem(index);
Indecies.Remove(key);
foreach (var k in Indecies.Keys.Where(k => Indecies[k] > index).ToList())
{
Indecies[k]--;
}
}
#endregion
public virtual bool ContainsKey(TKey key)
{
return Indecies.ContainsKey(key);
}
/// <summary>
/// Gets or sets the element with the specified key. If setting a new value, new value must have same key.
/// </summary>
/// <param name="key">Key of element to replace</param>
/// <returns></returns>
public virtual TValue this[TKey key]
{
get { return this[Indecies[key]]; }
set
{
//confirm key matches
if (!KeySelector(value).Equals(key))
throw new InvalidOperationException("Key of new value does not match");
if (!Indecies.ContainsKey(key))
{
this.Add(value);
}
else
{
this[Indecies[key]] = value;
}
}
}
/// <summary>
/// Replaces element at given key with new value. New value must have same key.
/// </summary>
/// <param name="key">Key of element to replace</param>
/// <param name="value">New value</param>
///
/// <exception cref="InvalidOperationException"></exception>
/// <returns>False if key not found</returns>
public virtual bool Replace(TKey key, TValue value)
{
if (!Indecies.ContainsKey(key)) return false;
//confirm key matches
if (!KeySelector(value).Equals(key))
throw new InvalidOperationException("Key of new value does not match");
this[Indecies[key]] = value;
return true;
}
public virtual bool Remove(TKey key)
{
if (!Indecies.ContainsKey(key)) return false;
this.RemoveAt(Indecies[key]);
return true;
}
/// <summary>
/// Allows us to change the key of an item
/// </summary>
/// <param name="currentKey"></param>
/// <param name="newKey"></param>
public virtual void ChangeKey(TKey currentKey, TKey newKey)
{
if (!Indecies.ContainsKey(currentKey))
{
throw new InvalidOperationException("No item with the key " + currentKey + "was found in the collection");
}
if (ContainsKey(newKey))
{
throw new DuplicateKeyException(newKey.ToString());
}
var currentIndex = Indecies[currentKey];
Indecies.Remove(currentKey);
Indecies.Add(newKey, currentIndex);
}
internal class DuplicateKeyException : Exception
{
public string Key { get; private set; }
public DuplicateKeyException(string key)
: base("Attempted to insert duplicate key " + key + " in collection")
{
Key = key;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace Umbraco.Core.Collections
{
/// <summary>
/// An ObservableDictionary
/// </summary>
/// <remarks>
/// Assumes that the key will not change and is unique for each element in the collection.
/// Collection is not thread-safe, so calls should be made single-threaded.
/// </remarks>
/// <typeparam name="TValue">The type of elements contained in the BindableCollection</typeparam>
/// <typeparam name="TKey">The type of the indexing key</typeparam>
public class ObservableDictionary<TKey, TValue> : ObservableCollection<TValue>
{
protected Dictionary<TKey, int> Indecies = new Dictionary<TKey, int>();
protected Func<TValue, TKey> KeySelector;
/// <summary>
/// Create new ObservableDictionary
/// </summary>
/// <param name="keySelector">Selector function to create key from value</param>
public ObservableDictionary(Func<TValue, TKey> keySelector)
: base()
{
if (keySelector == null) throw new ArgumentException("keySelector");
KeySelector = keySelector;
}
#region Protected Methods
protected override void InsertItem(int index, TValue item)
{
var key = KeySelector(item);
if (Indecies.ContainsKey(key))
throw new DuplicateKeyException(key.ToString());
if (index != this.Count)
{
foreach (var k in Indecies.Keys.Where(k => Indecies[k] >= index).ToList())
{
Indecies[k]++;
}
}
base.InsertItem(index, item);
Indecies[key] = index;
}
protected override void ClearItems()
{
base.ClearItems();
Indecies.Clear();
}
protected override void RemoveItem(int index)
{
var item = this[index];
var key = KeySelector(item);
base.RemoveItem(index);
Indecies.Remove(key);
foreach (var k in Indecies.Keys.Where(k => Indecies[k] > index).ToList())
{
Indecies[k]--;
}
}
#endregion
public virtual bool ContainsKey(TKey key)
{
return Indecies.ContainsKey(key);
}
/// <summary>
/// Gets or sets the element with the specified key. If setting a new value, new value must have same key.
/// </summary>
/// <param name="key">Key of element to replace</param>
/// <returns></returns>
public virtual TValue this[TKey key]
{
get { return this[Indecies[key]]; }
set
{
//confirm key matches
if (!KeySelector(value).Equals(key))
throw new InvalidOperationException("Key of new value does not match");
if (!Indecies.ContainsKey(key))
{
this.Add(value);
}
else
{
this[Indecies[key]] = value;
}
}
}
/// <summary>
/// Replaces element at given key with new value. New value must have same key.
/// </summary>
/// <param name="key">Key of element to replace</param>
/// <param name="value">New value</param>
///
/// <exception cref="InvalidOperationException"></exception>
/// <returns>False if key not found</returns>
public virtual bool Replace(TKey key, TValue value)
{
if (!Indecies.ContainsKey(key)) return false;
//confirm key matches
if (!KeySelector(value).Equals(key))
throw new InvalidOperationException("Key of new value does not match");
this[Indecies[key]] = value;
return true;
}
public virtual bool Remove(TKey key)
{
if (!Indecies.ContainsKey(key)) return false;
this.RemoveAt(Indecies[key]);
return true;
}
/// <summary>
/// Allows us to change the key of an item
/// </summary>
/// <param name="currentKey"></param>
/// <param name="newKey"></param>
public virtual void ChangeKey(TKey currentKey, TKey newKey)
{
if (!Indecies.ContainsKey(currentKey))
{
throw new InvalidOperationException("No item with the key " + currentKey + "was found in the collection");
}
if (ContainsKey(newKey))
{
throw new DuplicateKeyException(newKey.ToString());
}
var currentIndex = Indecies[currentKey];
Indecies.Remove(currentKey);
Indecies.Add(newKey, currentIndex);
}
internal class DuplicateKeyException : Exception
{
public string Key { get; private set; }
public DuplicateKeyException(string key)
: base("Attempted to insert duplicate key " + key + " in collection")
{
Key = key;
}
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using Umbraco.Core.Macros;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
@@ -183,19 +184,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
}
}
[Obsolete("This is here so that if this config element exists we won't get a YSOD, it is not used whatsoever and will be removed in future versions")]
[ConfigurationProperty("DocumentTypeIconList")]
internal InnerTextConfigurationElement<IconPickerBehaviour> DocumentTypeIconList
{
get
{
return new OptionalInnerTextConfigurationElement<IconPickerBehaviour>(
(InnerTextConfigurationElement<IconPickerBehaviour>)this["DocumentTypeIconList"],
//set the default
IconPickerBehaviour.HideFileDuplicates);
}
}
[ConfigurationProperty("disallowedUploadFiles")]
internal CommaDelimitedConfigurationElement DisallowedUploadFiles
{

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using Umbraco.Core.Macros;
namespace Umbraco.Core.Configuration.UmbracoSettings
{

View File

@@ -17,7 +17,7 @@ using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.Migrations;
using Umbraco.Core.Profiling;
using Umbraco.Core.Plugins;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;

View File

@@ -1,4 +1,5 @@
using LightInject;
using Umbraco.Core.Cache;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
@@ -6,6 +7,7 @@ using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Plugins;
namespace Umbraco.Core.DependencyInjection
{

View File

@@ -2,6 +2,7 @@ using System;
using System.IO;
using System.Linq;
using LightInject;
using Umbraco.Core.Cache;
using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;

View File

@@ -4,7 +4,6 @@ using System.ComponentModel;
using System.Diagnostics;
using System.Web;
using Umbraco.Core.Logging;
using Umbraco.Core.Profiling;
namespace Umbraco.Core
{

View File

@@ -11,6 +11,7 @@ using System.IO;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Xml;
namespace Umbraco.Core.Dynamics
{

View File

@@ -4,6 +4,7 @@ using System.Globalization;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Umbraco.Core.Plugins;
namespace Umbraco.Core.Dynamics
{

View File

@@ -9,6 +9,7 @@ using System.Text;
using System.Web.Services.Description;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Plugins;
namespace Umbraco.Core.Dynamics
{

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Umbraco.Core.Macros;
namespace Umbraco.Core.Events
{

View File

@@ -7,6 +7,7 @@ using System.Reflection;
using System.Text;
using Umbraco.Core.CodeAnnotations;
using Umbraco.Core.Configuration;
using Umbraco.Core.Plugins;
namespace Umbraco.Core.IO
{

View File

@@ -1,27 +0,0 @@
using System;
namespace Umbraco.Core
{
[Obsolete("This is no longer used and will be removed from the core in future versions")]
public enum IconPickerBehaviour
{
/// <summary>
/// Default umbraco behavior - show duplicates in files and sprites
/// </summary>
ShowDuplicates,
/// <summary>
/// If a file exists on disk with the same name as one in the sprite
/// then the file on disk overrules the one in the sprite, the
/// sprite icon will not be shown
/// </summary>
HideSpriteDuplicates,
/// <summary>
/// If a file exists on disk with the same name as one in the sprite
/// then the file in the sprite overrules the one on disk, the file
/// on disk will be shown
/// </summary>
HideFileDuplicates
}
}

View File

@@ -1,43 +1,43 @@
using System;
namespace Umbraco.Core.Profiling
{
/// <summary>
/// Defines an object for use in the application to profile operations
/// </summary>
public interface IProfiler
{
/// <summary>
/// Render the UI to display the profiler
/// </summary>
/// <returns></returns>
/// <remarks>
/// Generally used for HTML displays
/// </remarks>
string Render();
/// <summary>
/// Profile an operation
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
/// <remarks>
/// Use the 'using(' syntax
/// </remarks>
IDisposable Step(string name);
/// <summary>
/// Start the profiler
/// </summary>
void Start();
/// <summary>
/// Start the profiler
/// </summary>
/// <remarks>
/// set discardResults to false when you want to abandon all profiling, this is useful for
/// when someone is not authenticated or you want to clear the results based on some other mechanism.
/// </remarks>
void Stop(bool discardResults = false);
}
using System;
namespace Umbraco.Core.Logging
{
/// <summary>
/// Defines an object for use in the application to profile operations
/// </summary>
public interface IProfiler
{
/// <summary>
/// Render the UI to display the profiler
/// </summary>
/// <returns></returns>
/// <remarks>
/// Generally used for HTML displays
/// </remarks>
string Render();
/// <summary>
/// Profile an operation
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
/// <remarks>
/// Use the 'using(' syntax
/// </remarks>
IDisposable Step(string name);
/// <summary>
/// Start the profiler
/// </summary>
void Start();
/// <summary>
/// Start the profiler
/// </summary>
/// <remarks>
/// set discardResults to false when you want to abandon all profiling, this is useful for
/// when someone is not authenticated or you want to clear the results based on some other mechanism.
/// </remarks>
void Stop(bool discardResults = false);
}
}

View File

@@ -1,42 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Profiling
{
/// <summary>
/// A profiler that outputs its results to an ILogger
/// </summary>
internal class LogProfiler : IProfiler
{
private readonly ILogger _logger;
public LogProfiler(ILogger logger)
{
_logger = logger;
}
public string Render()
{
return string.Empty;
}
public IDisposable Step(string name)
{
_logger.Debug(typeof(LogProfiler), "Starting - " + name);
return new DisposableTimer(l => _logger.Info(typeof(LogProfiler), () => name + " (took " + l + "ms)"));
}
public void Start()
{
//the log will alwasy be started
}
public void Stop(bool discardResults = false)
{
//we don't need to do anything here
}
}
}
using System;
namespace Umbraco.Core.Logging
{
/// <summary>
/// A profiler that outputs its results to an ILogger
/// </summary>
internal class LogProfiler : IProfiler
{
private readonly ILogger _logger;
public LogProfiler(ILogger logger)
{
_logger = logger;
}
public string Render()
{
return string.Empty;
}
public IDisposable Step(string name)
{
_logger.Debug(typeof(LogProfiler), "Starting - " + name);
return new DisposableTimer(l => _logger.Info(typeof(LogProfiler), () => name + " (took " + l + "ms)"));
}
public void Start()
{
//the log will alwasy be started
}
public void Stop(bool discardResults = false)
{
//we don't need to do anything here
}
}
}

View File

@@ -1,35 +1,35 @@
using System;
namespace Umbraco.Core.Profiling
{
internal static class ProfilerExtensions
{
/// <summary>
/// Writes out a step prefixed with the type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="profiler"></param>
/// <param name="name"></param>
/// <returns></returns>
internal static IDisposable Step<T>(this IProfiler profiler, string name)
{
if (profiler == null) throw new ArgumentNullException("profiler");
return profiler.Step(typeof (T), name);
}
/// <summary>
/// Writes out a step prefixed with the type
/// </summary>
/// <param name="profiler"></param>
/// <param name="objectType"></param>
/// <param name="name"></param>
/// <returns></returns>
internal static IDisposable Step(this IProfiler profiler, Type objectType, string name)
{
if (profiler == null) throw new ArgumentNullException("profiler");
if (objectType == null) throw new ArgumentNullException("objectType");
if (name == null) throw new ArgumentNullException("name");
return profiler.Step(string.Format("[{0}] {1}", objectType.Name, name));
}
}
using System;
namespace Umbraco.Core.Logging
{
internal static class ProfilerExtensions
{
/// <summary>
/// Writes out a step prefixed with the type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="profiler"></param>
/// <param name="name"></param>
/// <returns></returns>
internal static IDisposable Step<T>(this IProfiler profiler, string name)
{
if (profiler == null) throw new ArgumentNullException("profiler");
return profiler.Step(typeof (T), name);
}
/// <summary>
/// Writes out a step prefixed with the type
/// </summary>
/// <param name="profiler"></param>
/// <param name="objectType"></param>
/// <param name="name"></param>
/// <returns></returns>
internal static IDisposable Step(this IProfiler profiler, Type objectType, string name)
{
if (profiler == null) throw new ArgumentNullException("profiler");
if (objectType == null) throw new ArgumentNullException("objectType");
if (name == null) throw new ArgumentNullException("name");
return profiler.Step(string.Format("[{0}] {1}", objectType.Name, name));
}
}
}

View File

@@ -1,42 +1,42 @@
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Core.Profiling
{
/// <summary>
/// A resolver exposing the current profiler
/// </summary>
/// <remarks>
/// NOTE: This is a 'special' resolver in that it gets initialized before most other things, it cannot use IoC so it cannot implement ContainerObjectResolverBase
/// </remarks>
internal class ProfilerResolver : SingleObjectResolverBase<ProfilerResolver, IProfiler>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="profiler"></param>
public ProfilerResolver(IProfiler profiler)
: base(profiler)
{
}
/// <summary>
/// Method allowing to change the profiler during startup
/// </summary>
/// <param name="profiler"></param>
internal void SetProfiler(IProfiler profiler)
{
Value = profiler;
}
/// <summary>
/// Gets the current profiler
/// </summary>
public IProfiler Profiler
{
get { return Value; }
}
}
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Core.Logging
{
/// <summary>
/// A resolver exposing the current profiler
/// </summary>
/// <remarks>
/// NOTE: This is a 'special' resolver in that it gets initialized before most other things, it cannot use IoC so it cannot implement ContainerObjectResolverBase
/// </remarks>
internal class ProfilerResolver : SingleObjectResolverBase<ProfilerResolver, IProfiler>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="profiler"></param>
public ProfilerResolver(IProfiler profiler)
: base(profiler)
{
}
/// <summary>
/// Method allowing to change the profiler during startup
/// </summary>
/// <param name="profiler"></param>
internal void SetProfiler(IProfiler profiler)
{
Value = profiler;
}
/// <summary>
/// Gets the current profiler
/// </summary>
public IProfiler Profiler
{
get { return Value; }
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using Umbraco.Core.Profiling;
namespace Umbraco.Core.Logging
{

View File

@@ -1,165 +1,164 @@
using System;
using System.Web;
using StackExchange.Profiling;
using StackExchange.Profiling.SqlFormatters;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Profiling
{
/// <summary>
/// A profiler used for web based activity based on the MiniProfiler framework
/// </summary>
internal class WebProfiler : ApplicationEventHandler, IProfiler
{
/// <summary>
///Binds to application events to enable the MiniProfiler
/// </summary>
/// <param name="umbracoApplication"></param>
/// <param name="applicationContext"></param>
protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
UmbracoApplicationBase.ApplicationInit += UmbracoApplicationApplicationInit;
}
/// <summary>
/// Handle the Init event o fthe UmbracoApplication which allows us to subscribe to the HttpApplication events
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void UmbracoApplicationApplicationInit(object sender, EventArgs e)
{
var app = sender as HttpApplication;
if (app == null) return;
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
{
//If we don't have a high enough trust level we cannot bind to the events
LogHelper.Info<WebProfiler>("Cannot start the WebProfiler since the application is running in Medium trust");
}
else
{
app.BeginRequest += UmbracoApplicationBeginRequest;
app.EndRequest += UmbracoApplicationEndRequest;
}
}
/// <summary>
/// Handle the begin request event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void UmbracoApplicationEndRequest(object sender, EventArgs e)
{
if (CanPerformProfilingAction(sender))
{
Stop();
}
}
/// <summary>
/// Handle the end request event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void UmbracoApplicationBeginRequest(object sender, EventArgs e)
{
if (CanPerformProfilingAction(sender))
{
Start();
}
}
private bool CanPerformProfilingAction(object sender)
{
if (GlobalSettings.DebugMode == false)
return false;
//will not run in medium trust
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
return false;
var request = TryGetRequest(sender);
if (request.Success == false || request.Result.Url.IsClientSideRequest())
return false;
if (string.IsNullOrEmpty(request.Result.QueryString["umbDebug"]))
return true;
if (request.Result.Url.IsBackOfficeRequest(HttpRuntime.AppDomainAppVirtualPath))
return true;
return true;
}
/// <summary>
/// Render the UI to display the profiler
/// </summary>
/// <returns></returns>
/// <remarks>
/// Generally used for HTML displays
/// </remarks>
public string Render()
{
return MiniProfiler.RenderIncludes(RenderPosition.Right).ToString();
}
/// <summary>
/// Profile a step
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
/// <remarks>
/// Use the 'using(' syntax
/// </remarks>
public IDisposable Step(string name)
{
return GlobalSettings.DebugMode == false ? null : MiniProfiler.Current.Step(name);
}
/// <summary>
/// Start the profiler
/// </summary>
public void Start()
{
MiniProfiler.Settings.SqlFormatter = new SqlServerFormatter();
MiniProfiler.Settings.StackMaxLength = 5000;
MiniProfiler.Start();
}
/// <summary>
/// Start the profiler
/// </summary>
/// <remarks>
/// set discardResults to false when you want to abandon all profiling, this is useful for
/// when someone is not authenticated or you want to clear the results based on some other mechanism.
/// </remarks>
public void Stop(bool discardResults = false)
{
MiniProfiler.Stop(discardResults);
}
/// <summary>
/// Gets the request object from the app instance if it is available
/// </summary>
/// <param name="sender">The application object</param>
/// <returns></returns>
private Attempt<HttpRequestBase> TryGetRequest(object sender)
{
var app = sender as HttpApplication;
if (app == null) return Attempt<HttpRequestBase>.Fail();
try
{
var req = app.Request;
return Attempt<HttpRequestBase>.Succeed(new HttpRequestWrapper(req));
}
catch (HttpException ex)
{
return Attempt<HttpRequestBase>.Fail(ex);
}
}
}
using System;
using System.Web;
using StackExchange.Profiling;
using StackExchange.Profiling.SqlFormatters;
using Umbraco.Core.Configuration;
namespace Umbraco.Core.Logging
{
/// <summary>
/// A profiler used for web based activity based on the MiniProfiler framework
/// </summary>
internal class WebProfiler : ApplicationEventHandler, IProfiler
{
/// <summary>
///Binds to application events to enable the MiniProfiler
/// </summary>
/// <param name="umbracoApplication"></param>
/// <param name="applicationContext"></param>
protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
UmbracoApplicationBase.ApplicationInit += UmbracoApplicationApplicationInit;
}
/// <summary>
/// Handle the Init event o fthe UmbracoApplication which allows us to subscribe to the HttpApplication events
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void UmbracoApplicationApplicationInit(object sender, EventArgs e)
{
var app = sender as HttpApplication;
if (app == null) return;
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
{
//If we don't have a high enough trust level we cannot bind to the events
LogHelper.Info<WebProfiler>("Cannot start the WebProfiler since the application is running in Medium trust");
}
else
{
app.BeginRequest += UmbracoApplicationBeginRequest;
app.EndRequest += UmbracoApplicationEndRequest;
}
}
/// <summary>
/// Handle the begin request event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void UmbracoApplicationEndRequest(object sender, EventArgs e)
{
if (CanPerformProfilingAction(sender))
{
Stop();
}
}
/// <summary>
/// Handle the end request event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void UmbracoApplicationBeginRequest(object sender, EventArgs e)
{
if (CanPerformProfilingAction(sender))
{
Start();
}
}
private bool CanPerformProfilingAction(object sender)
{
if (GlobalSettings.DebugMode == false)
return false;
//will not run in medium trust
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
return false;
var request = TryGetRequest(sender);
if (request.Success == false || request.Result.Url.IsClientSideRequest())
return false;
if (string.IsNullOrEmpty(request.Result.QueryString["umbDebug"]))
return true;
if (request.Result.Url.IsBackOfficeRequest(HttpRuntime.AppDomainAppVirtualPath))
return true;
return true;
}
/// <summary>
/// Render the UI to display the profiler
/// </summary>
/// <returns></returns>
/// <remarks>
/// Generally used for HTML displays
/// </remarks>
public string Render()
{
return MiniProfiler.RenderIncludes(RenderPosition.Right).ToString();
}
/// <summary>
/// Profile a step
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
/// <remarks>
/// Use the 'using(' syntax
/// </remarks>
public IDisposable Step(string name)
{
return GlobalSettings.DebugMode == false ? null : MiniProfiler.Current.Step(name);
}
/// <summary>
/// Start the profiler
/// </summary>
public void Start()
{
MiniProfiler.Settings.SqlFormatter = new SqlServerFormatter();
MiniProfiler.Settings.StackMaxLength = 5000;
MiniProfiler.Start();
}
/// <summary>
/// Start the profiler
/// </summary>
/// <remarks>
/// set discardResults to false when you want to abandon all profiling, this is useful for
/// when someone is not authenticated or you want to clear the results based on some other mechanism.
/// </remarks>
public void Stop(bool discardResults = false)
{
MiniProfiler.Stop(discardResults);
}
/// <summary>
/// Gets the request object from the app instance if it is available
/// </summary>
/// <param name="sender">The application object</param>
/// <returns></returns>
private Attempt<HttpRequestBase> TryGetRequest(object sender)
{
var app = sender as HttpApplication;
if (app == null) return Attempt<HttpRequestBase>.Fail();
try
{
var req = app.Request;
return Attempt<HttpRequestBase>.Succeed(new HttpRequestWrapper(req));
}
catch (HttpException ex)
{
return Attempt<HttpRequestBase>.Fail(ex);
}
}
}
}

View File

@@ -1,23 +1,23 @@
namespace Umbraco.Core
{
public enum MacroErrorBehaviour
{
/// <summary>
/// Default umbraco behavior - show an inline error within the
/// macro but allow the page to continue rendering.
/// </summary>
Inline,
/// <summary>
/// Silently eat the error and do not display the offending macro.
/// </summary>
Silent,
/// <summary>
/// Throw an exception which can be caught by the global error handler
/// defined in Application_OnError. If no such error handler is defined
/// then you'll see the Yellow Screen Of Death (YSOD) error page.
/// </summary>
Throw
}
}
namespace Umbraco.Core.Macros
{
public enum MacroErrorBehaviour
{
/// <summary>
/// Default umbraco behavior - show an inline error within the
/// macro but allow the page to continue rendering.
/// </summary>
Inline,
/// <summary>
/// Silently eat the error and do not display the offending macro.
/// </summary>
Silent,
/// <summary>
/// Throw an exception which can be caught by the global error handler
/// defined in Application_OnError. If no such error handler is defined
/// then you'll see the Yellow Screen Of Death (YSOD) error page.
/// </summary>
Throw
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using HtmlAgilityPack;
using Umbraco.Core.Xml;
namespace Umbraco.Core.Macros
{

View File

@@ -4,6 +4,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Umbraco.Core.Plugins;
namespace Umbraco.Core.Models
{

View File

@@ -5,6 +5,7 @@ using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Plugins;
namespace Umbraco.Core.Models.EntityBase
{

View File

@@ -2,6 +2,7 @@
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Collections;
namespace Umbraco.Core.Models
{

View File

@@ -6,6 +6,7 @@ using System.Xml.Linq;
using System.Xml.XPath;
using Umbraco.Core.Dynamics;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Xml;
namespace Umbraco.Core.Models.PublishedContent
{

View File

@@ -6,6 +6,7 @@ using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Xml;
using Umbraco.Core.Plugins;
namespace Umbraco.Core
{

View File

@@ -6,6 +6,7 @@ using System.Linq;
using System.Threading;
using System.Web;
using Umbraco.Core.Logging;
using Umbraco.Core.Plugins;
namespace Umbraco.Core.ObjectResolution
{

View File

@@ -7,6 +7,7 @@ using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Plugins;
namespace Umbraco.Core.Persistence.Querying
{

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using LightInject;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Xml.Linq;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;

View File

@@ -6,6 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Xml.Linq;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Identity;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Identity;

View File

@@ -1,4 +1,5 @@
using Umbraco.Core.Logging;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.UnitOfWork;

View File

@@ -1,4 +1,5 @@
using Umbraco.Core.Logging;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.UnitOfWork;

View File

@@ -1,4 +1,5 @@
using Umbraco.Core.Logging;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.UnitOfWork;

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;

View File

@@ -5,6 +5,7 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;

View File

@@ -4,6 +4,7 @@ using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;

View File

@@ -4,6 +4,7 @@ using System.Linq;
using LightInject;
using NPoco;
using Semver;
using Umbraco.Core.Cache;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data.SqlServerCe;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.Mappers;

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using LightInject;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using LightInject;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.Mappers;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;

View File

@@ -4,6 +4,7 @@ using System.Linq;
using AutoMapper;
using LightInject;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using LightInject;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Linq.Expressions;
using NPoco;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Models.Rdbms;

View File

@@ -6,6 +6,7 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;

View File

@@ -1,6 +1,6 @@
using System;
namespace Umbraco.Core
namespace Umbraco.Core.Plugins
{
/// <summary>
/// Used to notify the TypeFinder to ignore any class attributed with this during it's discovery

View File

@@ -1,311 +1,310 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Umbraco.Core
{
/// <summary>
/// A utility class for type checking, this provides internal caching so that calls to these methods will be faster
/// than doing a manual type check in c#
/// </summary>
internal static class TypeHelper
{
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache = new ConcurrentDictionary<Type, FieldInfo[]>();
private static readonly ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]> GetPropertiesCache = new ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]>();
/// <summary>
/// Find all assembly references that are referencing the assignTypeFrom Type's assembly found in the assemblyList
/// </summary>
/// <param name="assignTypeFrom"></param>
/// <param name="assemblies"></param>
/// <returns></returns>
/// <remarks>
/// If the assembly of the assignTypeFrom Type is in the App_Code assembly, then we return nothing since things cannot
/// reference that assembly, same with the global.asax assembly.
/// </remarks>
public static Assembly[] GetReferencedAssemblies(Type assignTypeFrom, IEnumerable<Assembly> assemblies)
{
//check if it is the app_code assembly.
//check if it is App_global.asax assembly
if (assignTypeFrom.Assembly.IsAppCodeAssembly() || assignTypeFrom.Assembly.IsGlobalAsaxAssembly())
{
return Enumerable.Empty<Assembly>().ToArray();
}
//find all assembly references that are referencing the current type's assembly since we
//should only be scanning those assemblies because any other assembly will definitely not
//contain sub type's of the one we're currently looking for
return assemblies
.Where(assembly =>
assembly == assignTypeFrom.Assembly
|| HasReferenceToAssemblyWithName(assembly, assignTypeFrom.Assembly.GetName().Name))
.ToArray();
}
/// <summary>
/// checks if the assembly has a reference with the same name as the expected assembly name.
/// </summary>
/// <param name="assembly"></param>
/// <param name="expectedAssemblyName"></param>
/// <returns></returns>
private static bool HasReferenceToAssemblyWithName(Assembly assembly, string expectedAssemblyName)
{
return assembly
.GetReferencedAssemblies()
.Select(a => a.Name)
.Contains(expectedAssemblyName, StringComparer.Ordinal);
}
/// <summary>
/// Returns true if the type is a class and is not static
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static bool IsNonStaticClass(Type t)
{
return t.IsClass && IsStaticClass(t) == false;
}
/// <summary>
/// Returns true if the type is a static class
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
/// <remarks>
/// In IL a static class is abstract and sealed
/// see: http://stackoverflow.com/questions/1175888/determine-if-a-type-is-static
/// </remarks>
public static bool IsStaticClass(Type type)
{
return type.IsAbstract && type.IsSealed;
}
/// <summary>
/// Finds a lowest base class amongst a collection of types
/// </summary>
/// <param name="types"></param>
/// <returns></returns>
/// <remarks>
/// The term 'lowest' refers to the most base class of the type collection.
/// If a base type is not found amongst the type collection then an invalid attempt is returned.
/// </remarks>
public static Attempt<Type> GetLowestBaseType(params Type[] types)
{
if (types.Length == 0)
{
return Attempt<Type>.Fail();
}
if (types.Length == 1)
{
return Attempt.Succeed(types[0]);
}
foreach (var curr in types)
{
var others = types.Except(new[] {curr});
//is the curr type a common denominator for all others ?
var isBase = others.All(curr.IsAssignableFrom);
//if this type is the base for all others
if (isBase)
{
return Attempt.Succeed(curr);
}
}
return Attempt<Type>.Fail();
}
/// <summary>
/// Determines whether the type <paramref name="implementation"/> is assignable from the specified implementation,
/// and caches the result across the application using a <see cref="ConcurrentDictionary{TKey,TValue}"/>.
/// </summary>
/// <param name="contract">The type of the contract.</param>
/// <param name="implementation">The implementation.</param>
/// <returns>
/// <c>true</c> if [is type assignable from] [the specified contract]; otherwise, <c>false</c>.
/// </returns>
public static bool IsTypeAssignableFrom(Type contract, Type implementation)
{
return contract.IsAssignableFrom(implementation);
}
/// <summary>
/// Determines whether the type <paramref name="implementation"/> is assignable from the specified implementation <typeparamref name="TContract"/>,
/// and caches the result across the application using a <see cref="ConcurrentDictionary{TKey,TValue}"/>.
/// </summary>
/// <typeparam name="TContract">The type of the contract.</typeparam>
/// <param name="implementation">The implementation.</param>
public static bool IsTypeAssignableFrom<TContract>(Type implementation)
{
return IsTypeAssignableFrom(typeof(TContract), implementation);
}
/// <summary>
/// Determines whether the object instance <paramref name="implementation"/> is assignable from the specified implementation <typeparamref name="TContract"/>,
/// and caches the result across the application using a <see cref="ConcurrentDictionary{TKey,TValue}"/>.
/// </summary>
/// <typeparam name="TContract">The type of the contract.</typeparam>
/// <param name="implementation">The implementation.</param>
public static bool IsTypeAssignableFrom<TContract>(object implementation)
{
if (implementation == null) throw new ArgumentNullException("implementation");
return IsTypeAssignableFrom<TContract>(implementation.GetType());
}
/// <summary>
/// Returns (and caches) a PropertyInfo from a type
/// </summary>
/// <param name="type"></param>
/// <param name="name"></param>
/// <param name="mustRead"></param>
/// <param name="mustWrite"></param>
/// <param name="includeIndexed"></param>
/// <param name="caseSensitive"> </param>
/// <returns></returns>
public static PropertyInfo GetProperty(Type type, string name,
bool mustRead = true,
bool mustWrite = true,
bool includeIndexed = false,
bool caseSensitive = true)
{
return CachedDiscoverableProperties(type, mustRead, mustWrite, includeIndexed)
.FirstOrDefault(x =>
{
if (caseSensitive)
return x.Name == name;
return x.Name.InvariantEquals(name);
});
}
/// <summary>
/// Gets (and caches) <see cref="PropertyInfo"/> discoverable in the current <see cref="AppDomain"/> for a given <paramref name="type"/>.
/// </summary>
/// <param name="type">The source.</param>
/// <param name="mustRead">true if the properties discovered are readable</param>
/// <param name="mustWrite">true if the properties discovered are writable</param>
/// <param name="includeIndexed">true if the properties discovered are indexable</param>
/// <returns></returns>
public static PropertyInfo[] CachedDiscoverableProperties(Type type, bool mustRead = true, bool mustWrite = true, bool includeIndexed = false)
{
return GetPropertiesCache.GetOrAdd(
new Tuple<Type, bool, bool, bool>(type, mustRead, mustWrite, includeIndexed),
x => type
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(y => (!mustRead || y.CanRead)
&& (!mustWrite || y.CanWrite)
&& (includeIndexed || !y.GetIndexParameters().Any()))
.ToArray());
}
#region Match Type
//TODO: Need to determine if these methods should replace/combine/merge etc with IsTypeAssignableFrom, IsAssignableFromGeneric
// readings:
// http://stackoverflow.com/questions/2033912/c-sharp-variance-problem-assigning-listderived-as-listbase
// http://stackoverflow.com/questions/2208043/generic-variance-in-c-sharp-4-0
// http://stackoverflow.com/questions/8401738/c-sharp-casting-generics-covariance-and-contravariance
// http://stackoverflow.com/questions/1827425/how-to-check-programatically-if-a-type-is-a-struct-or-a-class
// http://stackoverflow.com/questions/74616/how-to-detect-if-type-is-another-generic-type/1075059#1075059
private static bool MatchGeneric(Type implementation, Type contract, IDictionary<string, Type> bindings)
{
// trying to match eg List<int> with List<T>
// or List<List<List<int>>> with List<ListList<T>>>
// classes are NOT invariant so List<string> does not match List<object>
if (implementation.IsGenericType == false) return false;
// must have the same generic type definition
var implDef = implementation.GetGenericTypeDefinition();
var contDef = contract.GetGenericTypeDefinition();
if (implDef != contDef) return false;
// must have the same number of generic arguments
var implArgs = implementation.GetGenericArguments();
var contArgs = contract.GetGenericArguments();
if (implArgs.Length != contArgs.Length) return false;
// generic arguments must match
// in insta we should have actual types (eg int, string...)
// in typea we can have generic parameters (eg <T>)
for (var i = 0; i < implArgs.Length; i++)
{
const bool variance = false; // classes are NOT invariant
if (MatchType(implArgs[i], contArgs[i], bindings, variance) == false)
return false;
}
return true;
}
public static bool MatchType(Type implementation, Type contract)
{
return MatchType(implementation, contract, new Dictionary<string, Type>());
}
internal static bool MatchType(Type implementation, Type contract, IDictionary<string, Type> bindings, bool variance = true)
{
if (contract.IsGenericType)
{
// eg type is List<int> or List<T>
// if we have variance then List<int> can match IList<T>
// if we don't have variance it can't - must have exact type
// try to match implementation against contract
if (MatchGeneric(implementation, contract, bindings)) return true;
// if no variance, fail
if (variance == false) return false;
// try to match an ancestor of implementation against contract
var t = implementation.BaseType;
while (t != null)
{
if (MatchGeneric(t, contract, bindings)) return true;
t = t.BaseType;
}
// try to match an interface of implementation against contract
return implementation.GetInterfaces().Any(i => MatchGeneric(i, contract, bindings));
}
if (contract.IsGenericParameter)
{
// eg <T>
if (bindings.ContainsKey(contract.Name))
{
// already bound: ensure it's compatible
return bindings[contract.Name] == implementation;
}
// not already bound: bind
bindings[contract.Name] = implementation;
return true;
}
// not a generic type, not a generic parameter
// so normal class or interface
// fixme structs? enums? array types?
// about primitive types, value types, etc:
// http://stackoverflow.com/questions/1827425/how-to-check-programatically-if-a-type-is-a-struct-or-a-class
if (implementation == contract) return true;
if (contract.IsClass && implementation.IsClass && implementation.IsSubclassOf(contract)) return true;
if (contract.IsInterface && implementation.GetInterfaces().Contains(contract)) return true;
return false;
}
#endregion
}
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Umbraco.Core.Plugins
{
/// <summary>
/// A utility class for type checking, this provides internal caching so that calls to these methods will be faster
/// than doing a manual type check in c#
/// </summary>
internal static class TypeHelper
{
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache = new ConcurrentDictionary<Type, FieldInfo[]>();
private static readonly ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]> GetPropertiesCache = new ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]>();
/// <summary>
/// Find all assembly references that are referencing the assignTypeFrom Type's assembly found in the assemblyList
/// </summary>
/// <param name="assignTypeFrom"></param>
/// <param name="assemblies"></param>
/// <returns></returns>
/// <remarks>
/// If the assembly of the assignTypeFrom Type is in the App_Code assembly, then we return nothing since things cannot
/// reference that assembly, same with the global.asax assembly.
/// </remarks>
public static Assembly[] GetReferencedAssemblies(Type assignTypeFrom, IEnumerable<Assembly> assemblies)
{
//check if it is the app_code assembly.
//check if it is App_global.asax assembly
if (assignTypeFrom.Assembly.IsAppCodeAssembly() || assignTypeFrom.Assembly.IsGlobalAsaxAssembly())
{
return Enumerable.Empty<Assembly>().ToArray();
}
//find all assembly references that are referencing the current type's assembly since we
//should only be scanning those assemblies because any other assembly will definitely not
//contain sub type's of the one we're currently looking for
return assemblies
.Where(assembly =>
assembly == assignTypeFrom.Assembly
|| HasReferenceToAssemblyWithName(assembly, assignTypeFrom.Assembly.GetName().Name))
.ToArray();
}
/// <summary>
/// checks if the assembly has a reference with the same name as the expected assembly name.
/// </summary>
/// <param name="assembly"></param>
/// <param name="expectedAssemblyName"></param>
/// <returns></returns>
private static bool HasReferenceToAssemblyWithName(Assembly assembly, string expectedAssemblyName)
{
return assembly
.GetReferencedAssemblies()
.Select(a => a.Name)
.Contains(expectedAssemblyName, StringComparer.Ordinal);
}
/// <summary>
/// Returns true if the type is a class and is not static
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static bool IsNonStaticClass(Type t)
{
return t.IsClass && IsStaticClass(t) == false;
}
/// <summary>
/// Returns true if the type is a static class
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
/// <remarks>
/// In IL a static class is abstract and sealed
/// see: http://stackoverflow.com/questions/1175888/determine-if-a-type-is-static
/// </remarks>
public static bool IsStaticClass(Type type)
{
return type.IsAbstract && type.IsSealed;
}
/// <summary>
/// Finds a lowest base class amongst a collection of types
/// </summary>
/// <param name="types"></param>
/// <returns></returns>
/// <remarks>
/// The term 'lowest' refers to the most base class of the type collection.
/// If a base type is not found amongst the type collection then an invalid attempt is returned.
/// </remarks>
public static Attempt<Type> GetLowestBaseType(params Type[] types)
{
if (types.Length == 0)
{
return Attempt<Type>.Fail();
}
if (types.Length == 1)
{
return Attempt.Succeed(types[0]);
}
foreach (var curr in types)
{
var others = types.Except(new[] {curr});
//is the curr type a common denominator for all others ?
var isBase = others.All(curr.IsAssignableFrom);
//if this type is the base for all others
if (isBase)
{
return Attempt.Succeed(curr);
}
}
return Attempt<Type>.Fail();
}
/// <summary>
/// Determines whether the type <paramref name="implementation"/> is assignable from the specified implementation,
/// and caches the result across the application using a <see cref="ConcurrentDictionary{TKey,TValue}"/>.
/// </summary>
/// <param name="contract">The type of the contract.</param>
/// <param name="implementation">The implementation.</param>
/// <returns>
/// <c>true</c> if [is type assignable from] [the specified contract]; otherwise, <c>false</c>.
/// </returns>
public static bool IsTypeAssignableFrom(Type contract, Type implementation)
{
return contract.IsAssignableFrom(implementation);
}
/// <summary>
/// Determines whether the type <paramref name="implementation"/> is assignable from the specified implementation <typeparamref name="TContract"/>,
/// and caches the result across the application using a <see cref="ConcurrentDictionary{TKey,TValue}"/>.
/// </summary>
/// <typeparam name="TContract">The type of the contract.</typeparam>
/// <param name="implementation">The implementation.</param>
public static bool IsTypeAssignableFrom<TContract>(Type implementation)
{
return IsTypeAssignableFrom(typeof(TContract), implementation);
}
/// <summary>
/// Determines whether the object instance <paramref name="implementation"/> is assignable from the specified implementation <typeparamref name="TContract"/>,
/// and caches the result across the application using a <see cref="ConcurrentDictionary{TKey,TValue}"/>.
/// </summary>
/// <typeparam name="TContract">The type of the contract.</typeparam>
/// <param name="implementation">The implementation.</param>
public static bool IsTypeAssignableFrom<TContract>(object implementation)
{
if (implementation == null) throw new ArgumentNullException("implementation");
return IsTypeAssignableFrom<TContract>(implementation.GetType());
}
/// <summary>
/// Returns (and caches) a PropertyInfo from a type
/// </summary>
/// <param name="type"></param>
/// <param name="name"></param>
/// <param name="mustRead"></param>
/// <param name="mustWrite"></param>
/// <param name="includeIndexed"></param>
/// <param name="caseSensitive"> </param>
/// <returns></returns>
public static PropertyInfo GetProperty(Type type, string name,
bool mustRead = true,
bool mustWrite = true,
bool includeIndexed = false,
bool caseSensitive = true)
{
return CachedDiscoverableProperties(type, mustRead, mustWrite, includeIndexed)
.FirstOrDefault(x =>
{
if (caseSensitive)
return x.Name == name;
return x.Name.InvariantEquals(name);
});
}
/// <summary>
/// Gets (and caches) <see cref="PropertyInfo"/> discoverable in the current <see cref="AppDomain"/> for a given <paramref name="type"/>.
/// </summary>
/// <param name="type">The source.</param>
/// <param name="mustRead">true if the properties discovered are readable</param>
/// <param name="mustWrite">true if the properties discovered are writable</param>
/// <param name="includeIndexed">true if the properties discovered are indexable</param>
/// <returns></returns>
public static PropertyInfo[] CachedDiscoverableProperties(Type type, bool mustRead = true, bool mustWrite = true, bool includeIndexed = false)
{
return GetPropertiesCache.GetOrAdd(
new Tuple<Type, bool, bool, bool>(type, mustRead, mustWrite, includeIndexed),
x => type
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(y => (!mustRead || y.CanRead)
&& (!mustWrite || y.CanWrite)
&& (includeIndexed || !y.GetIndexParameters().Any()))
.ToArray());
}
#region Match Type
//TODO: Need to determine if these methods should replace/combine/merge etc with IsTypeAssignableFrom, IsAssignableFromGeneric
// readings:
// http://stackoverflow.com/questions/2033912/c-sharp-variance-problem-assigning-listderived-as-listbase
// http://stackoverflow.com/questions/2208043/generic-variance-in-c-sharp-4-0
// http://stackoverflow.com/questions/8401738/c-sharp-casting-generics-covariance-and-contravariance
// http://stackoverflow.com/questions/1827425/how-to-check-programatically-if-a-type-is-a-struct-or-a-class
// http://stackoverflow.com/questions/74616/how-to-detect-if-type-is-another-generic-type/1075059#1075059
private static bool MatchGeneric(Type implementation, Type contract, IDictionary<string, Type> bindings)
{
// trying to match eg List<int> with List<T>
// or List<List<List<int>>> with List<ListList<T>>>
// classes are NOT invariant so List<string> does not match List<object>
if (implementation.IsGenericType == false) return false;
// must have the same generic type definition
var implDef = implementation.GetGenericTypeDefinition();
var contDef = contract.GetGenericTypeDefinition();
if (implDef != contDef) return false;
// must have the same number of generic arguments
var implArgs = implementation.GetGenericArguments();
var contArgs = contract.GetGenericArguments();
if (implArgs.Length != contArgs.Length) return false;
// generic arguments must match
// in insta we should have actual types (eg int, string...)
// in typea we can have generic parameters (eg <T>)
for (var i = 0; i < implArgs.Length; i++)
{
const bool variance = false; // classes are NOT invariant
if (MatchType(implArgs[i], contArgs[i], bindings, variance) == false)
return false;
}
return true;
}
public static bool MatchType(Type implementation, Type contract)
{
return MatchType(implementation, contract, new Dictionary<string, Type>());
}
internal static bool MatchType(Type implementation, Type contract, IDictionary<string, Type> bindings, bool variance = true)
{
if (contract.IsGenericType)
{
// eg type is List<int> or List<T>
// if we have variance then List<int> can match IList<T>
// if we don't have variance it can't - must have exact type
// try to match implementation against contract
if (MatchGeneric(implementation, contract, bindings)) return true;
// if no variance, fail
if (variance == false) return false;
// try to match an ancestor of implementation against contract
var t = implementation.BaseType;
while (t != null)
{
if (MatchGeneric(t, contract, bindings)) return true;
t = t.BaseType;
}
// try to match an interface of implementation against contract
return implementation.GetInterfaces().Any(i => MatchGeneric(i, contract, bindings));
}
if (contract.IsGenericParameter)
{
// eg <T>
if (bindings.ContainsKey(contract.Name))
{
// already bound: ensure it's compatible
return bindings[contract.Name] == implementation;
}
// not already bound: bind
bindings[contract.Name] = implementation;
return true;
}
// not a generic type, not a generic parameter
// so normal class or interface
// fixme structs? enums? array types?
// about primitive types, value types, etc:
// http://stackoverflow.com/questions/1827425/how-to-check-programatically-if-a-type-is-a-struct-or-a-class
if (implementation == contract) return true;
if (contract.IsClass && implementation.IsClass && implementation.IsSubclassOf(contract)) return true;
if (contract.IsInterface && implementation.GetInterfaces().Contains(contract)) return true;
return false;
}
#endregion
}
}

View File

@@ -6,6 +6,7 @@ using Newtonsoft.Json;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Plugins;
namespace Umbraco.Core.PropertyEditors
{

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Plugins;
namespace Umbraco.Core
{

View File

@@ -7,6 +7,7 @@ using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using Umbraco.Core.Plugins;
using Umbraco.Core.Strings;
namespace Umbraco.Core

View File

@@ -148,7 +148,7 @@
<Compile Include="AssemblyExtensions.cs" />
<Compile Include="AsyncLock.cs" />
<Compile Include="AttemptOfT.cs" />
<Compile Include="CacheHelper.cs" />
<Compile Include="Cache\CacheHelper.cs" />
<Compile Include="Cache\CacheKeys.cs" />
<Compile Include="Cache\CacheProviderExtensions.cs" />
<Compile Include="Cache\DefaultRepositoryCachePolicy.cs" />
@@ -185,7 +185,7 @@
<Compile Include="CodeAnnotations\UmbracoExperimentalFeatureAttribute.cs" />
<Compile Include="Collections\DeepCloneableList.cs" />
<Compile Include="Collections\ListCloneBehavior.cs" />
<Compile Include="ConcurrentHashSet.cs" />
<Compile Include="Collections\ConcurrentHashSet.cs" />
<Compile Include="Configuration\CaseInsensitiveEnumConfigConverter.cs" />
<Compile Include="Configuration\ClientDependencyConfiguration.cs" />
<Compile Include="Configuration\Dashboard\AccessElement.cs" />
@@ -335,7 +335,7 @@
<DesignTime>True</DesignTime>
<DependentUpon>Files.resx</DependentUpon>
</Compile>
<Compile Include="HideFromTypeFinderAttribute.cs" />
<Compile Include="Plugins\HideFromTypeFinderAttribute.cs" />
<Compile Include="HttpContextExtensions.cs" />
<Compile Include="IApplicationEventHandler.cs" />
<Compile Include="IDisposeOnRequestEnd.cs" />
@@ -577,9 +577,8 @@
<Compile Include="Enum.cs" />
<Compile Include="Events\MacroErrorEventArgs.cs" />
<Compile Include="HashCodeCombiner.cs" />
<Compile Include="IconPickerBehaviour.cs" />
<Compile Include="IO\FileSystemWrapper.cs" />
<Compile Include="MacroErrorBehaviour.cs" />
<Compile Include="Macros\MacroErrorBehaviour.cs" />
<Compile Include="Media\IImageUrlProvider.cs" />
<Compile Include="Models\ContentPreviewEntity.cs" />
<Compile Include="Models\ContentTypeBase.cs" />
@@ -759,7 +758,7 @@
<Compile Include="Models\Validation\RequiredForPersistenceAttribute.cs" />
<Compile Include="ObjectResolution\ApplicationEventsResolver.cs" />
<Compile Include="ObjectResolution\ResolverCollection.cs" />
<Compile Include="ObservableDictionary.cs" />
<Compile Include="Collections\ObservableDictionary.cs" />
<Compile Include="Persistence\Factories\MacroFactory.cs" />
<Compile Include="Persistence\Factories\ModelFactoryConfiguration.cs" />
<Compile Include="Persistence\Factories\MemberFactory.cs" />
@@ -1070,11 +1069,11 @@
<Compile Include="Persistence\UnitOfWork\IUnitOfWorkRepository.cs" />
<Compile Include="Persistence\UnitOfWork\NPocoUnitOfWork.cs" />
<Compile Include="Persistence\UnitOfWork\NPocoUnitOfWorkProvider.cs" />
<Compile Include="Profiling\IProfiler.cs" />
<Compile Include="Profiling\LogProfiler.cs" />
<Compile Include="Profiling\ProfilerExtensions.cs" />
<Compile Include="Profiling\ProfilerResolver.cs" />
<Compile Include="Profiling\WebProfiler.cs" />
<Compile Include="Logging\IProfiler.cs" />
<Compile Include="Logging\LogProfiler.cs" />
<Compile Include="Logging\ProfilerExtensions.cs" />
<Compile Include="Logging\ProfilerResolver.cs" />
<Compile Include="Logging\WebProfiler.cs" />
<Compile Include="PropertyEditors\DelimitedManifestValueValidator.cs" />
<Compile Include="PropertyEditors\IntegerValidator.cs" />
<Compile Include="PropertyEditors\ManifestPropertyValidator.cs" />
@@ -1180,7 +1179,7 @@
<Compile Include="Dynamics\Signature.cs" />
<Compile Include="ExpressionExtensions.cs" />
<Compile Include="Models\IPublishedContent.cs" />
<Compile Include="CacheRefreshersResolver.cs" />
<Compile Include="Cache\CacheRefreshersResolver.cs" />
<Compile Include="Configuration\GlobalSettings.cs" />
<Compile Include="CustomBooleanTypeConverter.cs" />
<Compile Include="DisposableObject.cs" />
@@ -1320,8 +1319,8 @@
<Compile Include="Models\ApplicationTree.cs" />
<Compile Include="TypeExtensions.cs" />
<Compile Include="ReadLock.cs" />
<Compile Include="TypeFinder.cs" />
<Compile Include="TypeHelper.cs" />
<Compile Include="Plugins\TypeFinder.cs" />
<Compile Include="Plugins\TypeHelper.cs" />
<Compile Include="UmbracoApplicationBase.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Constants-Applications.cs">
@@ -1357,7 +1356,7 @@
<Compile Include="Media\Status.cs" />
<Compile Include="EnumerableExtensions.cs" />
<Compile Include="IfExtensions.cs" />
<Compile Include="PluginManager.cs" />
<Compile Include="Plugins\PluginManager.cs" />
<Compile Include="IO\FileSecurityException.cs" />
<Compile Include="IO\FileSystemProviderManager.cs" />
<Compile Include="IO\IFileSystem.cs" />
@@ -1375,7 +1374,7 @@
<Compile Include="WaitHandleExtensions.cs" />
<Compile Include="WriteLock.cs" />
<Compile Include="XmlExtensions.cs" />
<Compile Include="XmlHelper.cs" />
<Compile Include="Xml\XmlHelper.cs" />
<Compile Include="Xml\UmbracoXPathPathSyntaxParser.cs" />
<Compile Include="Xml\XPath\MacroNavigator.cs" />
<Compile Include="Xml\XPath\INavigableContentType.cs" />
@@ -1402,6 +1401,7 @@
<LastGenOutput>Files.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -1,470 +1,468 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
namespace Umbraco.Core
{
/// <summary>
/// The XmlHelper class contains general helper methods for working with xml in umbraco.
/// </summary>
public class XmlHelper
{
/// <summary>
/// Gets a value indicating whether a specified string contains only xml whitespace characters.
/// </summary>
/// <param name="s">The string.</param>
/// <returns><c>true</c> if the string contains only xml whitespace characters.</returns>
/// <remarks>As per XML 1.1 specs, space, \t, \r and \n.</remarks>
public static bool IsXmlWhitespace(string s)
{
// as per xml 1.1 specs - anything else is significant whitespace
s = s.Trim(' ', '\t', '\r', '\n');
return s.Length == 0;
}
/// <summary>
/// Creates a new <c>XPathDocument</c> from an xml string.
/// </summary>
/// <param name="xml">The xml string.</param>
/// <returns>An <c>XPathDocument</c> created from the xml string.</returns>
public static XPathDocument CreateXPathDocument(string xml)
{
return new XPathDocument(new XmlTextReader(new StringReader(xml)));
}
/// <summary>
/// Tries to create a new <c>XPathDocument</c> from an xml string.
/// </summary>
/// <param name="xml">The xml string.</param>
/// <param name="doc">The XPath document.</param>
/// <returns>A value indicating whether it has been possible to create the document.</returns>
public static bool TryCreateXPathDocument(string xml, out XPathDocument doc)
{
try
{
doc = CreateXPathDocument(xml);
return true;
}
catch (Exception)
{
doc = null;
return false;
}
}
/// <summary>
/// Tries to create a new <c>XPathDocument</c> from a property value.
/// </summary>
/// <param name="value">The value of the property.</param>
/// <param name="doc">The XPath document.</param>
/// <returns>A value indicating whether it has been possible to create the document.</returns>
/// <remarks>The value can be anything... Performance-wise, this is bad.</remarks>
public static bool TryCreateXPathDocumentFromPropertyValue(object value, out XPathDocument doc)
{
// DynamicNode.ConvertPropertyValueByDataType first cleans the value by calling
// XmlHelper.StripDashesInElementOrAttributeName - this is because the XML is
// to be returned as a DynamicXml and element names such as "value-item" are
// invalid and must be converted to "valueitem". But we don't have that sort of
// problem here - and we don't need to bother with dashes nor dots, etc.
doc = null;
var xml = value as string;
if (xml == null) return false; // no a string
if (CouldItBeXml(xml) == false) return false; // string does not look like it's xml
if (IsXmlWhitespace(xml)) return false; // string is whitespace, xml-wise
if (TryCreateXPathDocument(xml, out doc) == false) return false; // string can't be parsed into xml
var nav = doc.CreateNavigator();
if (nav.MoveToFirstChild())
{
//SD: This used to do this but the razor macros and the entire razor macros section is gone, it was all legacy, it seems this method isn't even
// used apart from for tests so don't think this matters. In any case, we no longer check for this!
//var name = nav.LocalName; // must not match an excluded tag
//if (UmbracoConfig.For.UmbracoSettings().Scripting.NotDynamicXmlDocumentElements.All(x => x.Element.InvariantEquals(name) == false)) return true;
return true;
}
doc = null;
return false;
}
/// <summary>
/// Tries to create a new <c>XElement</c> from a property value.
/// </summary>
/// <param name="value">The value of the property.</param>
/// <param name="elt">The Xml element.</param>
/// <returns>A value indicating whether it has been possible to create the element.</returns>
/// <remarks>The value can be anything... Performance-wise, this is bad.</remarks>
public static bool TryCreateXElementFromPropertyValue(object value, out XElement elt)
{
// see note above in TryCreateXPathDocumentFromPropertyValue...
elt = null;
var xml = value as string;
if (xml == null) return false; // not a string
if (CouldItBeXml(xml) == false) return false; // string does not look like it's xml
if (IsXmlWhitespace(xml)) return false; // string is whitespace, xml-wise
try
{
elt = XElement.Parse(xml, LoadOptions.None);
}
catch
{
elt = null;
return false; // string can't be parsed into xml
}
//SD: This used to do this but the razor macros and the entire razor macros section is gone, it was all legacy, it seems this method isn't even
// used apart from for tests so don't think this matters. In any case, we no longer check for this!
//var name = elt.Name.LocalName; // must not match an excluded tag
//if (UmbracoConfig.For.UmbracoSettings().Scripting.NotDynamicXmlDocumentElements.All(x => x.Element.InvariantEquals(name) == false))
// return true;
//elt = null;
//return false;
return true;
}
/// <summary>
/// Sorts the children of a parentNode.
/// </summary>
/// <param name="parentNode">The parent node.</param>
/// <param name="childNodesXPath">An XPath expression to select children of <paramref name="parentNode"/> to sort.</param>
/// <param name="orderBy">A function returning the value to order the nodes by.</param>
internal static void SortNodes(
XmlNode parentNode,
string childNodesXPath,
Func<XmlNode, int> orderBy)
{
var sortedChildNodes = parentNode.SelectNodes(childNodesXPath).Cast<XmlNode>()
.OrderBy(orderBy)
.ToArray();
// append child nodes to last position, in sort-order
// so all child nodes will go after the property nodes
foreach (var node in sortedChildNodes)
parentNode.AppendChild(node); // moves the node to the last position
}
/// <summary>
/// Sorts the children of a parentNode if needed.
/// </summary>
/// <param name="parentNode">The parent node.</param>
/// <param name="childNodesXPath">An XPath expression to select children of <paramref name="parentNode"/> to sort.</param>
/// <param name="orderBy">A function returning the value to order the nodes by.</param>
/// <returns>A value indicating whether sorting was needed.</returns>
/// <remarks>same as SortNodes but will do nothing if nodes are already sorted - should improve performances.</remarks>
internal static bool SortNodesIfNeeded(
XmlNode parentNode,
string childNodesXPath,
Func<XmlNode, int> orderBy)
{
// ensure orderBy runs only once per node
// checks whether nodes are already ordered
// and actually sorts only if needed
var childNodesAndOrder = parentNode.SelectNodes(childNodesXPath).Cast<XmlNode>()
.Select(x => Tuple.Create(x, orderBy(x))).ToArray();
var a = 0;
foreach (var x in childNodesAndOrder)
{
if (a > x.Item2)
{
a = -1;
break;
}
a = x.Item2;
}
if (a >= 0)
return false;
// append child nodes to last position, in sort-order
// so all child nodes will go after the property nodes
foreach (var x in childNodesAndOrder.OrderBy(x => x.Item2))
parentNode.AppendChild(x.Item1); // moves the node to the last position
return true;
}
/// <summary>
/// Sorts a single child node of a parentNode.
/// </summary>
/// <param name="parentNode">The parent node.</param>
/// <param name="childNodesXPath">An XPath expression to select children of <paramref name="parentNode"/> to sort.</param>
/// <param name="node">The child node to sort.</param>
/// <param name="orderBy">A function returning the value to order the nodes by.</param>
/// <returns>A value indicating whether sorting was needed.</returns>
/// <remarks>Assuming all nodes but <paramref name="node"/> are sorted, this will move the node to
/// the right position without moving all the nodes (as SortNodes would do) - should improve perfs.</remarks>
internal static bool SortNode(
XmlNode parentNode,
string childNodesXPath,
XmlNode node,
Func<XmlNode, int> orderBy)
{
var nodeSortOrder = orderBy(node);
var childNodesAndOrder = parentNode.SelectNodes(childNodesXPath).Cast<XmlNode>()
.Select(x => Tuple.Create(x, orderBy(x))).ToArray();
// find the first node with a sortOrder > node.sortOrder
var i = 0;
while (i < childNodesAndOrder.Length && childNodesAndOrder[i].Item2 <= nodeSortOrder)
i++;
// if one was found
if (i < childNodesAndOrder.Length)
{
// and node is just before, we're done already
// else we need to move it right before the node that was found
if (i > 0 && childNodesAndOrder[i - 1].Item1 != node)
{
parentNode.InsertBefore(node, childNodesAndOrder[i].Item1);
return true;
}
}
else
{
// and node is the last one, we're done already
// else we need to append it as the last one
if (i > 0 && childNodesAndOrder[i - 1].Item1 != node)
{
parentNode.AppendChild(node);
return true;
}
}
return false;
}
// used by DynamicNode only, see note in TryCreateXPathDocumentFromPropertyValue
public static string StripDashesInElementOrAttributeNames(string xml)
{
using (var outputms = new MemoryStream())
{
using (TextWriter outputtw = new StreamWriter(outputms))
{
using (var ms = new MemoryStream())
{
using (var tw = new StreamWriter(ms))
{
tw.Write(xml);
tw.Flush();
ms.Position = 0;
using (var tr = new StreamReader(ms))
{
bool IsInsideElement = false, IsInsideQuotes = false;
int ic = 0;
while ((ic = tr.Read()) != -1)
{
if (ic == (int)'<' && !IsInsideQuotes)
{
if (tr.Peek() != (int)'!')
{
IsInsideElement = true;
}
}
if (ic == (int)'>' && !IsInsideQuotes)
{
IsInsideElement = false;
}
if (ic == (int)'"')
{
IsInsideQuotes = !IsInsideQuotes;
}
if (!IsInsideElement || ic != (int)'-' || IsInsideQuotes)
{
outputtw.Write((char)ic);
}
}
}
}
}
outputtw.Flush();
outputms.Position = 0;
using (TextReader outputtr = new StreamReader(outputms))
{
return outputtr.ReadToEnd();
}
}
}
}
/// <summary>
/// Imports a XML node from text.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="xmlDoc">The XML doc.</param>
/// <returns></returns>
public static XmlNode ImportXmlNodeFromText(string text, ref XmlDocument xmlDoc)
{
xmlDoc.LoadXml(text);
return xmlDoc.FirstChild;
}
/// <summary>
/// Opens a file as a XmlDocument.
/// </summary>
/// <param name="filePath">The relative file path. ei. /config/umbraco.config</param>
/// <returns>Returns a XmlDocument class</returns>
public static XmlDocument OpenAsXmlDocument(string filePath)
{
var reader = new XmlTextReader(IOHelper.MapPath(filePath)) {WhitespaceHandling = WhitespaceHandling.All};
var xmlDoc = new XmlDocument();
//Load the file into the XmlDocument
xmlDoc.Load(reader);
//Close off the connection to the file.
reader.Close();
return xmlDoc;
}
/// <summary>
/// creates a XmlAttribute with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="name">The name of the attribute.</param>
/// <param name="value">The value of the attribute.</param>
/// <returns>a XmlAttribute</returns>
public static XmlAttribute AddAttribute(XmlDocument xd, string name, string value)
{
var temp = xd.CreateAttribute(name);
temp.Value = value;
return temp;
}
/// <summary>
/// Creates a text XmlNode with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="name">The node name.</param>
/// <param name="value">The node value.</param>
/// <returns>a XmlNode</returns>
public static XmlNode AddTextNode(XmlDocument xd, string name, string value)
{
var temp = xd.CreateNode(XmlNodeType.Element, name, "");
temp.AppendChild(xd.CreateTextNode(value));
return temp;
}
/// <summary>
/// Creates a cdata XmlNode with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="name">The node name.</param>
/// <param name="value">The node value.</param>
/// <returns>A XmlNode</returns>
public static XmlNode AddCDataNode(XmlDocument xd, string name, string value)
{
var temp = xd.CreateNode(XmlNodeType.Element, name, "");
temp.AppendChild(xd.CreateCDataSection(value));
return temp;
}
/// <summary>
/// Gets the value of a XmlNode
/// </summary>
/// <param name="n">The XmlNode.</param>
/// <returns>the value as a string</returns>
public static string GetNodeValue(XmlNode n)
{
var value = string.Empty;
if (n == null || n.FirstChild == null)
return value;
value = n.FirstChild.Value ?? n.InnerXml;
return value.Replace("<!--CDATAOPENTAG-->", "<![CDATA[").Replace("<!--CDATACLOSETAG-->", "]]>");
}
/// <summary>
/// Determines whether the specified string appears to be XML.
/// </summary>
/// <param name="xml">The XML string.</param>
/// <returns>
/// <c>true</c> if the specified string appears to be XML; otherwise, <c>false</c>.
/// </returns>
public static bool CouldItBeXml(string xml)
{
if (string.IsNullOrEmpty(xml)) return false;
xml = xml.Trim();
return xml.StartsWith("<") && xml.EndsWith(">") && xml.Contains('/');
}
/// <summary>
/// Splits the specified delimited string into an XML document.
/// </summary>
/// <param name="data">The data.</param>
/// <param name="separator">The separator.</param>
/// <param name="rootName">Name of the root.</param>
/// <param name="elementName">Name of the element.</param>
/// <returns>Returns an <c>System.Xml.XmlDocument</c> representation of the delimited string data.</returns>
public static XmlDocument Split(string data, string[] separator, string rootName, string elementName)
{
return Split(new XmlDocument(), data, separator, rootName, elementName);
}
/// <summary>
/// Splits the specified delimited string into an XML document.
/// </summary>
/// <param name="xml">The XML document.</param>
/// <param name="data">The delimited string data.</param>
/// <param name="separator">The separator.</param>
/// <param name="rootName">Name of the root node.</param>
/// <param name="elementName">Name of the element node.</param>
/// <returns>Returns an <c>System.Xml.XmlDocument</c> representation of the delimited string data.</returns>
public static XmlDocument Split(XmlDocument xml, string data, string[] separator, string rootName, string elementName)
{
// load new XML document.
xml.LoadXml(string.Concat("<", rootName, "/>"));
// get the data-value, check it isn't empty.
if (!string.IsNullOrEmpty(data))
{
// explode the values into an array
var values = data.Split(separator, StringSplitOptions.None);
// loop through the array items.
foreach (string value in values)
{
// add each value to the XML document.
var xn = XmlHelper.AddTextNode(xml, elementName, value);
xml.DocumentElement.AppendChild(xn);
}
}
// return the XML node.
return xml;
}
/// <summary>
/// Return a dictionary of attributes found for a string based tag
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public static Dictionary<string, string> GetAttributesFromElement(string tag)
{
var m =
Regex.Matches(tag, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
// fix for issue 14862: return lowercase attributes for case insensitive matching
var d = m.Cast<Match>().ToDictionary(attributeSet => attributeSet.Groups["attributeName"].Value.ToString().ToLower(), attributeSet => attributeSet.Groups["attributeValue"].Value.ToString());
return d;
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using Umbraco.Core.IO;
namespace Umbraco.Core.Xml
{
/// <summary>
/// The XmlHelper class contains general helper methods for working with xml in umbraco.
/// </summary>
public class XmlHelper
{
/// <summary>
/// Gets a value indicating whether a specified string contains only xml whitespace characters.
/// </summary>
/// <param name="s">The string.</param>
/// <returns><c>true</c> if the string contains only xml whitespace characters.</returns>
/// <remarks>As per XML 1.1 specs, space, \t, \r and \n.</remarks>
public static bool IsXmlWhitespace(string s)
{
// as per xml 1.1 specs - anything else is significant whitespace
s = s.Trim(' ', '\t', '\r', '\n');
return s.Length == 0;
}
/// <summary>
/// Creates a new <c>XPathDocument</c> from an xml string.
/// </summary>
/// <param name="xml">The xml string.</param>
/// <returns>An <c>XPathDocument</c> created from the xml string.</returns>
public static XPathDocument CreateXPathDocument(string xml)
{
return new XPathDocument(new XmlTextReader(new StringReader(xml)));
}
/// <summary>
/// Tries to create a new <c>XPathDocument</c> from an xml string.
/// </summary>
/// <param name="xml">The xml string.</param>
/// <param name="doc">The XPath document.</param>
/// <returns>A value indicating whether it has been possible to create the document.</returns>
public static bool TryCreateXPathDocument(string xml, out XPathDocument doc)
{
try
{
doc = CreateXPathDocument(xml);
return true;
}
catch (Exception)
{
doc = null;
return false;
}
}
/// <summary>
/// Tries to create a new <c>XPathDocument</c> from a property value.
/// </summary>
/// <param name="value">The value of the property.</param>
/// <param name="doc">The XPath document.</param>
/// <returns>A value indicating whether it has been possible to create the document.</returns>
/// <remarks>The value can be anything... Performance-wise, this is bad.</remarks>
public static bool TryCreateXPathDocumentFromPropertyValue(object value, out XPathDocument doc)
{
// DynamicNode.ConvertPropertyValueByDataType first cleans the value by calling
// XmlHelper.StripDashesInElementOrAttributeName - this is because the XML is
// to be returned as a DynamicXml and element names such as "value-item" are
// invalid and must be converted to "valueitem". But we don't have that sort of
// problem here - and we don't need to bother with dashes nor dots, etc.
doc = null;
var xml = value as string;
if (xml == null) return false; // no a string
if (CouldItBeXml(xml) == false) return false; // string does not look like it's xml
if (IsXmlWhitespace(xml)) return false; // string is whitespace, xml-wise
if (TryCreateXPathDocument(xml, out doc) == false) return false; // string can't be parsed into xml
var nav = doc.CreateNavigator();
if (nav.MoveToFirstChild())
{
//SD: This used to do this but the razor macros and the entire razor macros section is gone, it was all legacy, it seems this method isn't even
// used apart from for tests so don't think this matters. In any case, we no longer check for this!
//var name = nav.LocalName; // must not match an excluded tag
//if (UmbracoConfig.For.UmbracoSettings().Scripting.NotDynamicXmlDocumentElements.All(x => x.Element.InvariantEquals(name) == false)) return true;
return true;
}
doc = null;
return false;
}
/// <summary>
/// Tries to create a new <c>XElement</c> from a property value.
/// </summary>
/// <param name="value">The value of the property.</param>
/// <param name="elt">The Xml element.</param>
/// <returns>A value indicating whether it has been possible to create the element.</returns>
/// <remarks>The value can be anything... Performance-wise, this is bad.</remarks>
public static bool TryCreateXElementFromPropertyValue(object value, out XElement elt)
{
// see note above in TryCreateXPathDocumentFromPropertyValue...
elt = null;
var xml = value as string;
if (xml == null) return false; // not a string
if (CouldItBeXml(xml) == false) return false; // string does not look like it's xml
if (IsXmlWhitespace(xml)) return false; // string is whitespace, xml-wise
try
{
elt = XElement.Parse(xml, LoadOptions.None);
}
catch
{
elt = null;
return false; // string can't be parsed into xml
}
//SD: This used to do this but the razor macros and the entire razor macros section is gone, it was all legacy, it seems this method isn't even
// used apart from for tests so don't think this matters. In any case, we no longer check for this!
//var name = elt.Name.LocalName; // must not match an excluded tag
//if (UmbracoConfig.For.UmbracoSettings().Scripting.NotDynamicXmlDocumentElements.All(x => x.Element.InvariantEquals(name) == false))
// return true;
//elt = null;
//return false;
return true;
}
/// <summary>
/// Sorts the children of a parentNode.
/// </summary>
/// <param name="parentNode">The parent node.</param>
/// <param name="childNodesXPath">An XPath expression to select children of <paramref name="parentNode"/> to sort.</param>
/// <param name="orderBy">A function returning the value to order the nodes by.</param>
internal static void SortNodes(
XmlNode parentNode,
string childNodesXPath,
Func<XmlNode, int> orderBy)
{
var sortedChildNodes = parentNode.SelectNodes(childNodesXPath).Cast<XmlNode>()
.OrderBy(orderBy)
.ToArray();
// append child nodes to last position, in sort-order
// so all child nodes will go after the property nodes
foreach (var node in sortedChildNodes)
parentNode.AppendChild(node); // moves the node to the last position
}
/// <summary>
/// Sorts the children of a parentNode if needed.
/// </summary>
/// <param name="parentNode">The parent node.</param>
/// <param name="childNodesXPath">An XPath expression to select children of <paramref name="parentNode"/> to sort.</param>
/// <param name="orderBy">A function returning the value to order the nodes by.</param>
/// <returns>A value indicating whether sorting was needed.</returns>
/// <remarks>same as SortNodes but will do nothing if nodes are already sorted - should improve performances.</remarks>
internal static bool SortNodesIfNeeded(
XmlNode parentNode,
string childNodesXPath,
Func<XmlNode, int> orderBy)
{
// ensure orderBy runs only once per node
// checks whether nodes are already ordered
// and actually sorts only if needed
var childNodesAndOrder = parentNode.SelectNodes(childNodesXPath).Cast<XmlNode>()
.Select(x => Tuple.Create(x, orderBy(x))).ToArray();
var a = 0;
foreach (var x in childNodesAndOrder)
{
if (a > x.Item2)
{
a = -1;
break;
}
a = x.Item2;
}
if (a >= 0)
return false;
// append child nodes to last position, in sort-order
// so all child nodes will go after the property nodes
foreach (var x in childNodesAndOrder.OrderBy(x => x.Item2))
parentNode.AppendChild(x.Item1); // moves the node to the last position
return true;
}
/// <summary>
/// Sorts a single child node of a parentNode.
/// </summary>
/// <param name="parentNode">The parent node.</param>
/// <param name="childNodesXPath">An XPath expression to select children of <paramref name="parentNode"/> to sort.</param>
/// <param name="node">The child node to sort.</param>
/// <param name="orderBy">A function returning the value to order the nodes by.</param>
/// <returns>A value indicating whether sorting was needed.</returns>
/// <remarks>Assuming all nodes but <paramref name="node"/> are sorted, this will move the node to
/// the right position without moving all the nodes (as SortNodes would do) - should improve perfs.</remarks>
internal static bool SortNode(
XmlNode parentNode,
string childNodesXPath,
XmlNode node,
Func<XmlNode, int> orderBy)
{
var nodeSortOrder = orderBy(node);
var childNodesAndOrder = parentNode.SelectNodes(childNodesXPath).Cast<XmlNode>()
.Select(x => Tuple.Create(x, orderBy(x))).ToArray();
// find the first node with a sortOrder > node.sortOrder
var i = 0;
while (i < childNodesAndOrder.Length && childNodesAndOrder[i].Item2 <= nodeSortOrder)
i++;
// if one was found
if (i < childNodesAndOrder.Length)
{
// and node is just before, we're done already
// else we need to move it right before the node that was found
if (i > 0 && childNodesAndOrder[i - 1].Item1 != node)
{
parentNode.InsertBefore(node, childNodesAndOrder[i].Item1);
return true;
}
}
else
{
// and node is the last one, we're done already
// else we need to append it as the last one
if (i > 0 && childNodesAndOrder[i - 1].Item1 != node)
{
parentNode.AppendChild(node);
return true;
}
}
return false;
}
// used by DynamicNode only, see note in TryCreateXPathDocumentFromPropertyValue
public static string StripDashesInElementOrAttributeNames(string xml)
{
using (var outputms = new MemoryStream())
{
using (TextWriter outputtw = new StreamWriter(outputms))
{
using (var ms = new MemoryStream())
{
using (var tw = new StreamWriter(ms))
{
tw.Write(xml);
tw.Flush();
ms.Position = 0;
using (var tr = new StreamReader(ms))
{
bool IsInsideElement = false, IsInsideQuotes = false;
int ic = 0;
while ((ic = tr.Read()) != -1)
{
if (ic == (int)'<' && !IsInsideQuotes)
{
if (tr.Peek() != (int)'!')
{
IsInsideElement = true;
}
}
if (ic == (int)'>' && !IsInsideQuotes)
{
IsInsideElement = false;
}
if (ic == (int)'"')
{
IsInsideQuotes = !IsInsideQuotes;
}
if (!IsInsideElement || ic != (int)'-' || IsInsideQuotes)
{
outputtw.Write((char)ic);
}
}
}
}
}
outputtw.Flush();
outputms.Position = 0;
using (TextReader outputtr = new StreamReader(outputms))
{
return outputtr.ReadToEnd();
}
}
}
}
/// <summary>
/// Imports a XML node from text.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="xmlDoc">The XML doc.</param>
/// <returns></returns>
public static XmlNode ImportXmlNodeFromText(string text, ref XmlDocument xmlDoc)
{
xmlDoc.LoadXml(text);
return xmlDoc.FirstChild;
}
/// <summary>
/// Opens a file as a XmlDocument.
/// </summary>
/// <param name="filePath">The relative file path. ei. /config/umbraco.config</param>
/// <returns>Returns a XmlDocument class</returns>
public static XmlDocument OpenAsXmlDocument(string filePath)
{
var reader = new XmlTextReader(IOHelper.MapPath(filePath)) {WhitespaceHandling = WhitespaceHandling.All};
var xmlDoc = new XmlDocument();
//Load the file into the XmlDocument
xmlDoc.Load(reader);
//Close off the connection to the file.
reader.Close();
return xmlDoc;
}
/// <summary>
/// creates a XmlAttribute with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="name">The name of the attribute.</param>
/// <param name="value">The value of the attribute.</param>
/// <returns>a XmlAttribute</returns>
public static XmlAttribute AddAttribute(XmlDocument xd, string name, string value)
{
var temp = xd.CreateAttribute(name);
temp.Value = value;
return temp;
}
/// <summary>
/// Creates a text XmlNode with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="name">The node name.</param>
/// <param name="value">The node value.</param>
/// <returns>a XmlNode</returns>
public static XmlNode AddTextNode(XmlDocument xd, string name, string value)
{
var temp = xd.CreateNode(XmlNodeType.Element, name, "");
temp.AppendChild(xd.CreateTextNode(value));
return temp;
}
/// <summary>
/// Creates a cdata XmlNode with the specified name and value
/// </summary>
/// <param name="xd">The xmldocument.</param>
/// <param name="name">The node name.</param>
/// <param name="value">The node value.</param>
/// <returns>A XmlNode</returns>
public static XmlNode AddCDataNode(XmlDocument xd, string name, string value)
{
var temp = xd.CreateNode(XmlNodeType.Element, name, "");
temp.AppendChild(xd.CreateCDataSection(value));
return temp;
}
/// <summary>
/// Gets the value of a XmlNode
/// </summary>
/// <param name="n">The XmlNode.</param>
/// <returns>the value as a string</returns>
public static string GetNodeValue(XmlNode n)
{
var value = string.Empty;
if (n == null || n.FirstChild == null)
return value;
value = n.FirstChild.Value ?? n.InnerXml;
return value.Replace("<!--CDATAOPENTAG-->", "<![CDATA[").Replace("<!--CDATACLOSETAG-->", "]]>");
}
/// <summary>
/// Determines whether the specified string appears to be XML.
/// </summary>
/// <param name="xml">The XML string.</param>
/// <returns>
/// <c>true</c> if the specified string appears to be XML; otherwise, <c>false</c>.
/// </returns>
public static bool CouldItBeXml(string xml)
{
if (string.IsNullOrEmpty(xml)) return false;
xml = xml.Trim();
return xml.StartsWith("<") && xml.EndsWith(">") && xml.Contains('/');
}
/// <summary>
/// Splits the specified delimited string into an XML document.
/// </summary>
/// <param name="data">The data.</param>
/// <param name="separator">The separator.</param>
/// <param name="rootName">Name of the root.</param>
/// <param name="elementName">Name of the element.</param>
/// <returns>Returns an <c>System.Xml.XmlDocument</c> representation of the delimited string data.</returns>
public static XmlDocument Split(string data, string[] separator, string rootName, string elementName)
{
return Split(new XmlDocument(), data, separator, rootName, elementName);
}
/// <summary>
/// Splits the specified delimited string into an XML document.
/// </summary>
/// <param name="xml">The XML document.</param>
/// <param name="data">The delimited string data.</param>
/// <param name="separator">The separator.</param>
/// <param name="rootName">Name of the root node.</param>
/// <param name="elementName">Name of the element node.</param>
/// <returns>Returns an <c>System.Xml.XmlDocument</c> representation of the delimited string data.</returns>
public static XmlDocument Split(XmlDocument xml, string data, string[] separator, string rootName, string elementName)
{
// load new XML document.
xml.LoadXml(string.Concat("<", rootName, "/>"));
// get the data-value, check it isn't empty.
if (!string.IsNullOrEmpty(data))
{
// explode the values into an array
var values = data.Split(separator, StringSplitOptions.None);
// loop through the array items.
foreach (string value in values)
{
// add each value to the XML document.
var xn = XmlHelper.AddTextNode(xml, elementName, value);
xml.DocumentElement.AppendChild(xn);
}
}
// return the XML node.
return xml;
}
/// <summary>
/// Return a dictionary of attributes found for a string based tag
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public static Dictionary<string, string> GetAttributesFromElement(string tag)
{
var m =
Regex.Matches(tag, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
// fix for issue 14862: return lowercase attributes for case insensitive matching
var d = m.Cast<Match>().ToDictionary(attributeSet => attributeSet.Groups["attributeName"].Value.ToString().ToLower(), attributeSet => attributeSet.Groups["attributeValue"].Value.ToString());
return d;
}
}
}

View File

@@ -4,6 +4,7 @@ using Moq;
using NUnit.Framework;
using Semver;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;

View File

@@ -4,6 +4,7 @@ using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;

View File

@@ -5,6 +5,7 @@ using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Macros;
namespace Umbraco.Tests.Configurations.UmbracoSettings
{

View File

@@ -10,6 +10,7 @@ using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Migrations;
using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Plugins;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings;

View File

@@ -16,6 +16,7 @@ using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Profiling;
using Umbraco.Core.Services;
using Moq;
using Umbraco.Core.Cache;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Routing;

View File

@@ -5,6 +5,7 @@ using System.Linq;
using AutoMapper;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Core.PropertyEditors;
@@ -27,8 +28,8 @@ namespace Umbraco.Tests.Models.Mapping
Logger,
typeListProducerList,
new ManifestBuilder(
Core.CacheHelper.CreateDisabledCacheHelper().RuntimeCache,
new ManifestParser(Logger, new DirectoryInfo(TestHelper.CurrentAssemblyDirectory), Core.CacheHelper.CreateDisabledCacheHelper().RuntimeCache)));
CacheHelper.CreateDisabledCacheHelper().RuntimeCache,
new ManifestParser(Logger, new DirectoryInfo(TestHelper.CurrentAssemblyDirectory), CacheHelper.CreateDisabledCacheHelper().RuntimeCache)));
PropertyEditorResolver.Current = propertyEditorResolver;

View File

@@ -6,6 +6,7 @@ using Moq;
using NPoco;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;

View File

@@ -10,6 +10,7 @@ using NPoco;
using NUnit.Framework;
using Semver;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;

View File

@@ -5,6 +5,7 @@ using AutoMapper;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;

View File

@@ -3,6 +3,7 @@ using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;

View File

@@ -3,6 +3,7 @@ using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;

View File

@@ -3,6 +3,7 @@ using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;

View File

@@ -3,6 +3,7 @@ using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;

View File

@@ -3,6 +3,7 @@ using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;

View File

@@ -4,6 +4,7 @@ using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence;

View File

@@ -2,6 +2,7 @@
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence;

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Umbraco.Core;
using Umbraco.Core.Plugins;
namespace Umbraco.Tests.Plugins
{

View File

@@ -18,6 +18,7 @@ using Umbraco.Core.Profiling;
using Umbraco.Core.PropertyEditors;
using umbraco.DataLayer;
using umbraco.uicontrols;
using Umbraco.Core.Plugins;
using Umbraco.Web;
using Umbraco.Web.PropertyEditors;

View File

@@ -19,6 +19,7 @@ using Umbraco.Core;
using Umbraco.Core.IO;
using umbraco.DataLayer;
using umbraco.uicontrols;
using Umbraco.Core.Plugins;
using Umbraco.Web;
using Umbraco.Web.Models.Trees;
using Umbraco.Web.Trees;

View File

@@ -10,6 +10,7 @@ using System.Reflection;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Plugins;
using Umbraco.Tests.DynamicsAndReflection;
using Umbraco.Web.Cache;
using Umbraco.Web.Models;

View File

@@ -4,6 +4,7 @@ using System.Globalization;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Profiling;

View File

@@ -9,6 +9,7 @@ using Umbraco.Core;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Dynamics;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Plugins;
using Umbraco.Core.PropertyEditors;
using Umbraco.Tests.TestHelpers;

View File

@@ -3,6 +3,7 @@ using System.Xml.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Dynamics;
using Umbraco.Core.Xml;
namespace Umbraco.Tests.PublishedContent
{

View File

@@ -5,6 +5,7 @@ using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Dynamics;
using System.Linq;
using Umbraco.Core.Xml;
namespace Umbraco.Tests.PublishedContent
{

View File

@@ -11,6 +11,7 @@ using Umbraco.Core.PropertyEditors;
using Umbraco.Web;
using Umbraco.Tests.TestHelpers;
using umbraco.BusinessLogic;
using Umbraco.Core.Plugins;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
using Umbraco.Web.Security;

View File

@@ -6,6 +6,7 @@ using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Plugins;
using Umbraco.Core.PropertyEditors;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;

View File

@@ -5,6 +5,7 @@ using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Plugins;
using Umbraco.Core.Profiling;
using Umbraco.Core._Legacy.PackageActions;

View File

@@ -13,6 +13,7 @@ using Umbraco.Web.Mvc;
using Umbraco.Web.Routing;
using Umbraco.Web.WebApi;
using umbraco.BusinessLogic;
using Umbraco.Core.Plugins;
using Umbraco.Core.Profiling;
using Umbraco.Core.Strings;

View File

@@ -6,6 +6,7 @@ using Microsoft.Owin;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;

View File

@@ -2,6 +2,7 @@
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;

View File

@@ -9,6 +9,7 @@ using System.Threading;
using NPoco;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;

View File

@@ -8,6 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using NPoco;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;

View File

@@ -26,6 +26,7 @@ using Umbraco.Web.PublishedCache;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
using Umbraco.Web.Security;
using Umbraco.Core.Events;
using Umbraco.Core.Plugins;
using File = System.IO.File;
namespace Umbraco.Tests.TestHelpers

View File

@@ -23,6 +23,7 @@ using Umbraco.Web;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Events;
using Umbraco.Core.Plugins;
using Umbraco.Web.DependencyInjection;
namespace Umbraco.Tests.TestHelpers

Some files were not shown because too many files have changed in this diff Show More