Merge branch '6.2.0-pubcontent' into 7.0.0-pubcontent

Conflicts:
	src/Umbraco.Core/Cache/CacheProviderBase.cs
	src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs
	src/Umbraco.Core/Cache/NullCacheProvider.cs
	src/Umbraco.Core/Cache/StaticCacheProvider.cs
	src/Umbraco.Core/Configuration/UmbracoSettings.cs
	src/Umbraco.Core/CoreBootManager.cs
	src/Umbraco.Core/Dynamics/PropertyResult.cs
	src/Umbraco.Core/Models/IPublishedContentProperty.cs
	src/Umbraco.Core/Models/PublishedItemType.cs
	src/Umbraco.Core/PropertyEditors/IPropertyEditorValueConverter.cs
	src/Umbraco.Core/PropertyEditors/PropertyEditorValueConvertersResolver.cs
	src/Umbraco.Core/PropertyEditors/PropertyValueConvertersResolver.cs
	src/Umbraco.Core/PublishedContentExtensions.cs
	src/Umbraco.Core/PublishedContentHelper.cs
	src/Umbraco.Core/Umbraco.Core.csproj
	src/Umbraco.Tests/CodeFirst/StronglyTypedMapperTest.cs
	src/Umbraco.Tests/LibraryTests.cs
	src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs
	src/Umbraco.Tests/PublishedCache/PublishedContentCacheTests.cs
	src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs
	src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs
	src/Umbraco.Web/ExamineExtensions.cs
	src/Umbraco.Web/Models/DynamicPublishedContent.cs
	src/Umbraco.Web/Models/XmlPublishedContent.cs
	src/Umbraco.Web/Models/XmlPublishedContentProperty.cs
	src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs
	src/Umbraco.Web/PublishedContentExtensions.cs
	src/Umbraco.Web/Templates/TemplateUtilities.cs
	src/Umbraco.Web/Umbraco.Web.csproj
	src/Umbraco.Web/WebBootManager.cs
	src/Umbraco.Web/umbraco.presentation/macro.cs
	src/umbraco.MacroEngines/RazorDynamicNode/PropertyResult.cs
	src/umbraco.MacroEngines/RazorDynamicNode/PublishedContentExtensions.cs
This commit is contained in:
Stephan
2013-09-23 21:57:22 +02:00
138 changed files with 10417 additions and 6251 deletions

View File

@@ -112,7 +112,8 @@ namespace Umbraco.Core.Dynamics
{
//don't log here, we return this exception because the caller may need to do something specific when
//this exception occurs.
return Attempt<TryInvokeMemberResult>.Fail(ext);
var mresult = new TryInvokeMemberResult(null, TryInvokeMemberSuccessReason.FoundExtensionMethod);
return Attempt<TryInvokeMemberResult>.Fail(mresult, ext);
}
catch (Exception ex)
{
@@ -124,7 +125,8 @@ namespace Umbraco.Core.Dynamics
sb.Append(t + ",");
}
LogHelper.Error<DynamicInstanceHelper>(sb.ToString(), ex);
return Attempt<TryInvokeMemberResult>.Fail(ex);
var mresult = new TryInvokeMemberResult(null, TryInvokeMemberSuccessReason.FoundExtensionMethod);
return Attempt<TryInvokeMemberResult>.Fail(mresult, ex);
}
}
return Attempt<TryInvokeMemberResult>.Fail();

View File

@@ -11,78 +11,101 @@ namespace Umbraco.Core.Dynamics
//Because it's IEnumerable, if the user is actually trying @Model.TextPages or similar
//it will still return an enumerable object (assuming the call actually failed because there were no children of that type)
//but in .Where, if they use a property that doesn't exist, the lambda will bypass this and return false
// returned when TryGetMember fails on a DynamicPublishedContent
//
// so if user does @CurrentPage.TextPages it will get something that is enumerable (but empty)
// note - not sure I understand the stuff about .Where, though
public class DynamicNull : DynamicObject, IEnumerable, IHtmlString
{
public static readonly DynamicNull Null = new DynamicNull();
private DynamicNull() {}
public IEnumerator GetEnumerator()
{
return (new List<DynamicNull>()).GetEnumerator();
}
public DynamicNull Where(string predicate, params object[] values)
{
return this;
}
public DynamicNull OrderBy(string orderBy)
{
return this;
}
public DynamicNull ToContentSet()
{
return this;
}
public int Count()
{
return 0;
}
public override string ToString()
{
return string.Empty;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = this;
return true;
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
result = this;
return true;
}
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
result = this;
return true;
}
public bool IsNull()
{
return true;
}
public bool HasValue()
{
return false;
}
public string Name
{
get
{
return string.Empty;
}
get { return string.Empty; }
}
public int Id
{
get
{
return 0;
}
get { return 0; }
}
public static implicit operator bool(DynamicNull n)
{
return false;
}
public static implicit operator DateTime(DynamicNull n)
{
return DateTime.MinValue;
}
public static implicit operator int(DynamicNull n)
{
return 0;
}
public static implicit operator string(DynamicNull n)
{
return string.Empty;
@@ -92,6 +115,5 @@ namespace Umbraco.Core.Dynamics
{
return string.Empty;
}
}
}

View File

@@ -203,7 +203,7 @@ namespace Umbraco.Core.Dynamics
if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod
&& attempt.Exception != null && attempt.Exception is TargetInvocationException)
{
result = new DynamicNull();
result = DynamicNull.Null;
return true;
}

View File

@@ -13,7 +13,96 @@ namespace Umbraco.Core.Dynamics
/// Utility class for finding extension methods on a type to execute
/// </summary>
internal static class ExtensionMethodFinder
{
{
private static readonly MethodInfo[] AllExtensionMethods;
static ExtensionMethodFinder()
{
AllExtensionMethods = TypeFinder.GetAssembliesWithKnownExclusions()
// assemblies that contain extension methods
.Where(a => a.IsDefined(typeof(ExtensionAttribute), false))
// types that contain extension methods
.SelectMany(a => a.GetTypes()
.Where(t => t.IsDefined(typeof(ExtensionAttribute), false) && t.IsSealed && t.IsGenericType == false && t.IsNested == false))
// actual extension methods
.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(m => m.IsDefined(typeof(ExtensionAttribute), false)))
// and also IEnumerable<T> extension methods - because the assembly is excluded
.Concat(typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public))
.ToArray();
}
// ORIGINAL CODE IS NOT COMPLETE, DOES NOT HANDLE GENERICS, ETC...
// so this is an attempt at fixing things, but it's not done yet
// and do we really want to do this? extension methods are not supported on dynamics, period
// we should use strongly typed content instead of dynamics.
/*
// get all extension methods for type thisType, with name name,
// accepting argsCount arguments (not counting the instance of thisType).
private static IEnumerable<MethodInfo> GetExtensionMethods(Type thisType, string name, int argsCount)
{
var key = string.Format("{0}.{1}::{2}", thisType.FullName, name, argsCount);
var types = thisType.GetBaseTypes(true); // either do this OR have MatchFirstParameter handle the stuff... F*XME
var methods = AllExtensionMethods
.Where(m => m.Name == name)
.Where(m => m.GetParameters().Length == argsCount)
.Where(m => MatchFirstParameter(thisType, m.GetParameters()[0].ParameterType));
// f*xme - is this what we should cache?
return methods;
}
// find out whether the first parameter is a match for thisType
private static bool MatchFirstParameter(Type thisType, Type firstParameterType)
{
return MethodArgZeroHasCorrectTargetType(null, firstParameterType, thisType);
}
// get the single extension method for type thisType, with name name,
// that accepts the arguments in args (which does not contain the instance of thisType).
public static MethodInfo GetExtensionMethod(Type thisType, string name, object[] args)
{
MethodInfo result = null;
foreach (var method in GetExtensionMethods(thisType, name, args.Length).Where(m => MatchParameters(m, args)))
{
if (result == null)
result = method;
else
throw new AmbiguousMatchException("More than one matching extension method was found.");
}
return result;
}
// find out whether the method can accept the arguments
private static bool MatchParameters(MethodInfo method, IList<object> args)
{
var parameters = method.GetParameters();
var i = 0;
for (; i < parameters.Length; ++i)
{
if (MatchParameter(parameters[i].ParameterType, args[i].GetType()) == false)
break;
}
return (i == parameters.Length);
}
internal static bool MatchParameter(Type parameterType, Type argumentType)
{
// public static int DoSomething<T>(Foo foo, T t1, T t2)
// DoSomething(foo, t1, t2) => how can we match?!
return parameterType == argumentType; // f*xme of course!
}
*
*/
// BELOW IS THE ORIGINAL CODE...
/// <summary>
/// Returns all extension methods found matching the definition
/// </summary>
@@ -27,6 +116,10 @@ namespace Umbraco.Core.Dynamics
/// </remarks>
private static IEnumerable<MethodInfo> GetAllExtensionMethods(Type thisType, string name, int argumentCount, bool argsContainsThis)
{
// at *least* we can cache the extension methods discovery
var candidates = AllExtensionMethods;
/*
//only scan assemblies we know to contain extension methods (user assemblies)
var assembliesToScan = TypeFinder.GetAssembliesWithKnownExclusions();
@@ -45,6 +138,7 @@ namespace Umbraco.Core.Dynamics
//add the extension methods defined in IEnumerable
candidates = candidates.Concat(typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public));
*/
//filter by name
var methodsByName = candidates.Where(m => m.Name == name);

View File

@@ -1,60 +1,46 @@
using System;
using Umbraco.Core.Models;
using umbraco.interfaces;
using System.Web;
namespace Umbraco.Core.Dynamics
{
internal class PropertyResult : IPublishedContentProperty, IHtmlString
{
internal PropertyResult(IPublishedContentProperty source, PropertyResultType type)
internal class PropertyResult : IPublishedProperty, IHtmlString
{
private readonly IPublishedProperty _source;
private readonly string _alias;
private readonly object _value;
private readonly PropertyResultType _type;
internal PropertyResult(IPublishedProperty source, PropertyResultType type)
{
if (source == null) throw new ArgumentNullException("source");
Alias = source.Alias;
Value = source.Value;
PropertyType = type;
_type = type;
_source = source;
}
internal PropertyResult(string alias, object value, PropertyResultType type)
{
if (alias == null) throw new ArgumentNullException("alias");
if (value == null) throw new ArgumentNullException("value");
Alias = alias;
Value = value;
PropertyType = type;
_type = type;
_alias = alias;
_value = value;
}
internal PropertyResultType PropertyType { get; private set; }
public string Alias { get; private set; }
internal PropertyResultType PropertyType { get { return _type; } }
public object Value { get; private set; }
/// <summary>
/// Returns the value as a string output, this is used in the final rendering process of a property
/// </summary>
internal string ValueAsString
{
get
{
return Value == null ? "" : Convert.ToString(Value);
}
}
/// <summary>
/// The Id of the document for which this property belongs to
/// </summary>
public int DocumentId { get; set; }
/// <summary>
/// The alias of the document type alias for which this property belongs to
/// </summary>
public string DocumentTypeAlias { get; set; }
public string PropertyTypeAlias { get { return _source == null ? _alias : _source.PropertyTypeAlias; } }
public object DataValue { get { return _source == null ? _value : _source.DataValue; } }
public bool HasValue { get { return _source == null || _source.HasValue; } }
public object ObjectValue { get { return _source == null ? _value : _source.ObjectValue; } }
public object XPathValue { get { return ObjectValue == null ? null : ObjectValue.ToString(); } }
public string ToHtmlString()
{
return ValueAsString;
var value = ObjectValue;
return value == null ? string.Empty : value.ToString();
}
}
}