private static object Liquidize(object obj) { if (obj == null) { return(obj); } if (obj is ILiquidizable) { return(((ILiquidizable)obj).ToLiquid()); } if (obj is string) { return(obj); } if (obj.GetType().IsPrimitive) { return(obj); } if (obj is decimal) { return(obj); } if (obj is DateTime) { return(obj); } if (obj is TimeSpan) { return(obj); } if (obj is Guid) { return(obj); } if (TypeUtility.IsAnonymousType(obj.GetType())) { return(obj); } if (obj is KeyValuePair <string, object> ) { return(obj); } var safeTypeTransformer = Template.GetSafeTypeTransformer(obj.GetType()); if (safeTypeTransformer != null) { return(safeTypeTransformer(obj)); } if (obj is IEnumerable) //$ Moved to avoid try a Table (ContainedDetail) as IEnumerable. Previously, this was just between 'string' and '...IsPrimitive'. { return(obj); } if (obj.GetType().GetCustomAttributes(typeof(LiquidTypeAttribute), false).Any()) //$? Also gets attributes of ancestors { var attr = (LiquidTypeAttribute)obj.GetType().GetCustomAttributes(typeof(LiquidTypeAttribute), false).First(); //$? Also gets attributes of ancestors return(new DropProxy(obj, attr.AllowedMembers)); } throw new SyntaxException(Liquid.ResourceManager.GetString("ContextObjectInvalidException"), obj.ToString()); }
private static object Liquidize(object obj) { if (obj == null) { return(obj); } if (obj is ILiquidizable) { return(((ILiquidizable)obj).ToLiquid()); } if (obj is string) { return(obj); } if (obj is IEnumerable) { return(obj); } if (obj.GetType().IsPrimitive) { return(obj); } if (obj is decimal) { return(obj); } if (obj is DateTime) { return(obj); } if (obj is TimeSpan) { return(obj); } if (obj is Guid) { return(obj); } if (TypeUtility.IsAnonymousType(obj.GetType())) { return(obj); } if (obj is KeyValuePair <string, object> ) { return(obj); } var safeTypeTransformer = Template.GetSafeTypeTransformer(obj.GetType()); if (safeTypeTransformer != null) { return(safeTypeTransformer(obj)); } if (obj.GetType().GetCustomAttributes(typeof(LiquidTypeAttribute), false).Any()) { var attr = (LiquidTypeAttribute)obj.GetType().GetCustomAttributes(typeof(LiquidTypeAttribute), false).First(); return(new DropProxy(obj, attr.AllowedMembers)); } throw new SyntaxException(Liquid.ResourceManager.GetString("ContextObjectInvalidException"), obj.ToString()); }
/// <summary> /// Map/collect on a given property /// </summary> /// <param name="enumerableInput">The enumerable.</param> /// <param name="property">The property to map.</param> public static IEnumerable Map(IEnumerable enumerableInput, string property) { if (enumerableInput == null) { return(null); } // Enumerate to a list so we can repeatedly parse through the collection. List <object> listedInput = enumerableInput.Cast <object>().ToList(); // If the list happens to be empty we are done already. if (!listedInput.Any()) { return(listedInput); } // Note that liquid assumes that contained complex elements are all following the same schema. // Hence here we only check if the first element has the property requested for the map. if (listedInput.All(element => element is IDictionary) && ((IDictionary)listedInput.First()).Contains(key: property)) { return(listedInput.Select(element => ((IDictionary)element)[property])); } return(listedInput .Select(selector: element => { if (element == null) { return null; } var indexable = element as IIndexable; if (indexable == null) { var type = element.GetType(); var safeTypeTransformer = Template.GetSafeTypeTransformer(type); if (safeTypeTransformer != null) { indexable = safeTypeTransformer(element) as DropBase; } else { var liquidTypeAttribute = type .GetTypeInfo() .GetCustomAttributes(attributeType: typeof(LiquidTypeAttribute), inherit: false) .FirstOrDefault() as LiquidTypeAttribute; if (liquidTypeAttribute != null) { indexable = new DropProxy(element, liquidTypeAttribute.AllowedMembers); } else if (TypeUtility.IsAnonymousType(type)) { return element.RespondTo(property) ? element.Send(property) : element; } } } return (indexable?.ContainsKey(property) ?? false) ? indexable[property] : null; })); }