Merge with 6.0.3

This commit is contained in:
Shannon Deminick
2013-03-05 08:42:43 +06:00

View File

@@ -48,6 +48,7 @@ namespace umbraco.MacroEngines
private DynamicNodeList _cachedChildren;
private readonly ConcurrentDictionary<string, object> _cachedMemberOutput = new ConcurrentDictionary<string, object>();
private readonly ConcurrentDictionary<string, PropertyResult> _cachedProperties = new ConcurrentDictionary<string, PropertyResult>();
internal readonly DynamicBackingItem n;
@@ -462,12 +463,82 @@ namespace umbraco.MacroEngines
return GetDataTypeCallback(docTypeAlias, propertyAlias);
}
/// <summary>
/// Returns the value from the property result and ensure it is filtered through the razor data type converters
/// </summary>
/// <param name="propResult"></param>
/// <param name="result">The value result for the property</param>
/// <returns>true if getting the property data was successful</returns>
private bool TryGetPropertyData(PropertyResult propResult, out object result)
{
if (propResult == null) throw new ArgumentNullException("propResult");
//special casing for true/false properties
//int/decimal are handled by ConvertPropertyValueByDataType
//fallback is stringT
if (n.NodeTypeAlias == null && propResult.Alias == null)
{
throw new ArgumentNullException("No node alias or property alias available. Unable to look up the datatype of the property you are trying to fetch.");
}
//contextAlias is the node which the property data was returned from
//Guid dataType = ContentType.GetDataType(data.ContextAlias, data.Alias);
var dataType = GetDataType(propResult.ContextAlias, propResult.Alias);
var staticMapping = UmbracoSettings.RazorDataTypeModelStaticMapping
.FirstOrDefault(mapping => mapping.Applies(dataType, propResult.ContextAlias, propResult.Alias));
if (staticMapping != null)
{
var dataTypeType = Type.GetType(staticMapping.TypeName);
if (dataTypeType != null)
{
object valueOutput = null;
if (TryCreateInstanceRazorDataTypeModel(dataType, dataTypeType, propResult.Value, out valueOutput))
{
result = valueOutput;
return true;
}
LogHelper.Warn<DynamicNode>(string.Format("Failed to create the instance of the model binder"));
}
else
{
LogHelper.Warn<DynamicNode>(string.Format("staticMapping type name {0} came back as null from Type.GetType; check the casing, assembly presence, assembly framework version, namespace", staticMapping.TypeName));
}
}
if (RazorDataTypeModelTypes != null && RazorDataTypeModelTypes.Any(model => model.Key.Item1 == dataType) && dataType != Guid.Empty)
{
var razorDataTypeModelDefinition = RazorDataTypeModelTypes.Where(model => model.Key.Item1 == dataType).OrderByDescending(model => model.Key.Item2).FirstOrDefault();
if (!(razorDataTypeModelDefinition.Equals(default(KeyValuePair<System.Tuple<Guid, int>, Type>))))
{
Type dataTypeType = razorDataTypeModelDefinition.Value;
object valueResult = null;
if (TryCreateInstanceRazorDataTypeModel(dataType, dataTypeType, propResult.Value, out valueResult))
{
result = valueResult;
return true;
}
LogHelper.Warn<DynamicNode>(string.Format("Failed to create the instance of the model binder"));
}
else
{
LogHelper.Warn<DynamicNode>(string.Format("Could not get the dataTypeType for the RazorDataTypeModel"));
}
}
result = propResult.Value;
//convert the string value to a known type
var returnVal = ConvertPropertyValueByDataType(ref result, propResult.Alias, dataType);
return returnVal;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var name = binder.Name;
//check the cache first!
if (_cachedMemberOutput.TryGetValue(name, out result))
if (_cachedMemberOutput.TryGetValue(binder.Name, out result))
{
return true;
}
@@ -478,7 +549,7 @@ namespace umbraco.MacroEngines
{
result = GetChildrenAsList;
//cache the result so we don't have to re-process the whole thing
_cachedMemberOutput.TryAdd(name, result);
_cachedMemberOutput.TryAdd(binder.Name, result);
return true;
}
if (binder.Name.InvariantEquals("parentId"))
@@ -489,7 +560,7 @@ namespace umbraco.MacroEngines
throw new InvalidOperationException(string.Format("The node {0} does not have a parent", Id));
}
result = parent.Id;
_cachedMemberOutput.TryAdd(name, result);
_cachedMemberOutput.TryAdd(binder.Name, result);
return true;
}
@@ -502,87 +573,26 @@ namespace umbraco.MacroEngines
name = name.Substring(1, name.Length - 1);
recursive = true;
}
var data = n.GetProperty(name, recursive, out propertyExists);
// check for nicer support of Pascal Casing EVEN if alias is camelCasing:
if (data == null && name.Substring(0, 1).ToUpper() == name.Substring(0, 1) && !propertyExists)
PropertyResult prop;
if (!_cachedProperties.TryGetValue(binder.Name, out prop))
{
data = n.GetProperty(name.Substring(0, 1).ToLower() + name.Substring((1)), recursive, out propertyExists);
prop = n.GetProperty(name, recursive, out propertyExists);
// check for nicer support of Pascal Casing EVEN if alias is camelCasing:
if (prop == null && name.Substring(0, 1).ToUpper() == name.Substring(0, 1) && !propertyExists)
{
prop = n.GetProperty(name.Substring(0, 1).ToLower() + name.Substring((1)), recursive, out propertyExists);
}
}
if (data != null)
if (prop != null)
{
result = data.Value;
//special casing for true/false properties
//int/decimal are handled by ConvertPropertyValueByDataType
//fallback is stringT
if (n.NodeTypeAlias == null && data.Alias == null)
if (TryGetPropertyData(prop, out result))
{
throw new ArgumentNullException("No node alias or property alias available. Unable to look up the datatype of the property you are trying to fetch.");
//cache the result so we don't have to re-process the whole thing
_cachedMemberOutput.TryAdd(binder.Name, result);
return true;
}
//contextAlias is the node which the property data was returned from
//Guid dataType = ContentType.GetDataType(data.ContextAlias, data.Alias);
var dataType = GetDataType(data.ContextAlias, data.Alias);
var staticMapping = UmbracoSettings.RazorDataTypeModelStaticMapping.FirstOrDefault(mapping =>
{
return mapping.Applies(dataType, data.ContextAlias, data.Alias);
});
if (staticMapping != null)
{
Type dataTypeType = Type.GetType(staticMapping.TypeName);
if (dataTypeType != null)
{
object instance = null;
if (TryCreateInstanceRazorDataTypeModel(dataType, dataTypeType, data.Value, out instance))
{
result = instance;
//cache the result so we don't have to re-process the whole thing
_cachedMemberOutput.TryAdd(name, result);
return true;
}
else
{
LogHelper.Warn<DynamicNode>(string.Format("Failed to create the instance of the model binder"));
}
}
else
{
LogHelper.Warn<DynamicNode>(string.Format("staticMapping type name {0} came back as null from Type.GetType; check the casing, assembly presence, assembly framework version, namespace", staticMapping.TypeName));
}
}
if (RazorDataTypeModelTypes != null && RazorDataTypeModelTypes.Any(model => model.Key.Item1 == dataType) && dataType != Guid.Empty)
{
var razorDataTypeModelDefinition = RazorDataTypeModelTypes.Where(model => model.Key.Item1 == dataType).OrderByDescending(model => model.Key.Item2).FirstOrDefault();
if (!(razorDataTypeModelDefinition.Equals(default(KeyValuePair<System.Tuple<Guid, int>, Type>))))
{
Type dataTypeType = razorDataTypeModelDefinition.Value;
object instance = null;
if (TryCreateInstanceRazorDataTypeModel(dataType, dataTypeType, data.Value, out instance))
{
result = instance;
//cache the result so we don't have to re-process the whole thing
_cachedMemberOutput.TryAdd(name, result);
return true;
}
else
{
LogHelper.Warn<DynamicNode>(string.Format("Failed to create the instance of the model binder"));
}
}
else
{
LogHelper.Warn<DynamicNode>(string.Format("Could not get the dataTypeType for the RazorDataTypeModel"));
}
}
//convert the string value to a known type
var returnVal = ConvertPropertyValueByDataType(ref result, name, dataType);
//cache the result so we don't have to re-process the whole thing
_cachedMemberOutput.TryAdd(name, result);
return returnVal;
}
//check if the alias is that of a child type
@@ -598,7 +608,7 @@ namespace umbraco.MacroEngines
{
result = new DynamicNodeList(filteredTypeChildren);
//cache the result so we don't have to re-process the whole thing
_cachedMemberOutput.TryAdd(name, result);
_cachedMemberOutput.TryAdd(binder.Name, result);
return true;
}
@@ -610,7 +620,7 @@ namespace umbraco.MacroEngines
if (result != null)
{
_cachedMemberOutput.TryAdd(name, result);
_cachedMemberOutput.TryAdd(binder.Name, result);
return true;
}
@@ -1333,14 +1343,12 @@ namespace umbraco.MacroEngines
{
if (n == null) return null;
object result;
IProperty prop;
PropertyResult prop;
//check the cache first!
if (_cachedMemberOutput.TryGetValue(alias, out result))
{
prop = result as IProperty;
if (prop != null)
return prop;
if (_cachedProperties.TryGetValue(alias, out prop))
{
return prop;
}
try
@@ -1366,7 +1374,7 @@ namespace umbraco.MacroEngines
return null;
//cache it!
_cachedMemberOutput.TryAdd(alias, prop);
_cachedProperties.TryAdd(alias, prop);
return prop;
}