/// <summary>Returns the processed value for the given type and property.</summary> /// <param name="content">The <see cref="IPublishedContent" /> to convert.</param> /// <param name="culture">The <see cref="CultureInfo" /></param> /// <param name="config">The Ditto configuration for the type.</param> /// <param name="mappableProperty">Information about the mappable property.</param> /// <param name="instance">The instance to assign the value to.</param> /// <param name="chainContext">The <see cref="DittoChainContext"/> for the current processor chain.</param> /// <returns>The <see cref="object" /> representing the Umbraco value.</returns> private static object GetProcessedValue( IPublishedContent content, CultureInfo culture, DittoTypeInfo config, DittoTypeInfo.DittoTypePropertyInfo mappableProperty, object instance, DittoChainContext chainContext) { using (DittoDisposableTimer.DebugDuration(typeof(Ditto), $"Processing '{mappableProperty.PropertyInfo.Name}' ({content.Id})")) { // Create a base processor context for this current chain level var baseProcessorContext = new DittoProcessorContext { Content = content, TargetType = config.TargetType, PropertyInfo = mappableProperty.PropertyInfo, Culture = culture }; // Check for cache attribute if (mappableProperty.IsCacheable) { var ctx = new DittoCacheContext(mappableProperty.CacheInfo, content, config.TargetType, mappableProperty.PropertyInfo, culture); return(mappableProperty.CacheInfo.GetCacheItem(ctx, () => DoGetProcessedValue(content, mappableProperty, baseProcessorContext, chainContext))); } else { return(DoGetProcessedValue(content, mappableProperty, baseProcessorContext, chainContext)); } } }
/// <summary>Returns the processed value for the given type and property.</summary> /// <param name="content">The content.</param> /// <param name="mappableProperty">Information about the mappable property.</param> /// <param name="baseProcessorContext">The base processor context.</param> /// <param name="chainContext">The <see cref="DittoChainContext"/> for the current processor chain.</param> /// <returns>Returns the processed value.</returns> private static object DoGetProcessedValue( IPublishedContent content, DittoTypeInfo.DittoTypePropertyInfo mappableProperty, DittoProcessorContext baseProcessorContext, DittoChainContext chainContext) { // Create holder for value as it's processed object currentValue = content; // Process attributes foreach (var processorAttr in mappableProperty.Processors) { using (DittoDisposableTimer.DebugDuration(typeof(Ditto), $"Processor '{processorAttr}' ({content.Id})")) { // Get the right context type var ctx = chainContext.ProcessorContexts.GetOrCreate(baseProcessorContext, processorAttr.ContextType); // Populate UmbracoContext & ApplicationContext processorAttr.UmbracoContext = ContextAccessor.UmbracoContext; processorAttr.ApplicationContext = ContextAccessor.ApplicationContext; // Process value currentValue = processorAttr.ProcessValue(currentValue, ctx, chainContext); } } // The following has to happen after all the processors. if (mappableProperty.IsEnumerable && currentValue != null && currentValue.Equals(Enumerable.Empty <object>())) { if (mappableProperty.PropertyInfo.PropertyType.IsInterface) { // You cannot set an enumerable of type from an empty object array. currentValue = EnumerableInvocations.Cast(mappableProperty.EnumerableType, (IEnumerable)currentValue); } else { // This should allow the casting back of IEnumerable<T> to an empty List<T> Collection<T> etc. // I cant think of any that don't have an empty constructor currentValue = mappableProperty.PropertyInfo.PropertyType.GetInstance(); } } return(currentValue == null && mappableProperty.PropertyInfo.PropertyType.IsValueType ? mappableProperty.PropertyInfo.PropertyType.GetInstance() // Set to default instance of value type : currentValue); }