Last active
January 19, 2020 21:48
-
-
Save Hendy/da5d8a67e1711d195c9a to your computer and use it in GitHub Desktop.
Ditto That Ditto
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Our.Umbraco.Ditto; | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
using System.Globalization; | |
using System.Reflection; | |
using Umbraco.Core.Models; | |
namespace Example.TypeConverters | |
{ | |
/* Ditto that Ditto | |
* If the value supplied to Ditto is IPublishedContent, or a collection of IPublishedContent | |
* (eg as returned by Nested Content) and the return type on the model property is a different | |
* object (or collection of), then attempt to re-Ditto it. Eg: | |
* | |
* [TypeConverter(typeof(PublishedContentTypeConverter))] | |
* public IEnumerable<MyPoco> MyProperty { get; set; } | |
* | |
* so if the value supplied to Ditto for MyProperty is a collection of IPublishedContent, | |
* then this type converter will attempt to convert IEnumerable<IPublishedContent> | |
* into IEnumerable<MyPoco> | |
*/ | |
public class PublishedContentTypeConverter : TypeConverter | |
{ | |
/// <summary> | |
/// check to see if this can perform the conversion | |
/// </summary> | |
/// <param name="context">contains the specification of the output type</param> | |
/// <param name="sourceType">the input type</param> | |
/// <returns>true if this type converter can do the conversion</returns> | |
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) | |
{ | |
return | |
( | |
typeof(IEnumerable<IPublishedContent>).IsAssignableFrom(sourceType) | |
&& context.PropertyDescriptor.PropertyType.IsGenericType | |
&& context.PropertyDescriptor.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>) | |
&& context.PropertyDescriptor.PropertyType.GenericTypeArguments[0] != sourceType.GenericTypeArguments[0] | |
) | |
|| | |
( | |
typeof(IPublishedContent).IsAssignableFrom(sourceType) | |
&& !context.PropertyDescriptor.PropertyType.IsGenericType | |
&& context.PropertyDescriptor.PropertyType != sourceType | |
); | |
} | |
/// <summary> | |
/// attempt to perform the conversion | |
/// </summary> | |
/// <param name="context">contains the specification of the output type</param> | |
/// <param name="culture"></param> | |
/// <param name="value">expected to an IEnumerable of IPublishedContent or a single IPublishedContent</param> | |
/// <returns>null, or a single item, or a list of items as specified by the model property return type</returns> | |
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) | |
{ | |
MethodInfo dittoAs = typeof(PublishedContentExtensions) | |
.GetMethod( | |
"As", | |
BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly, | |
null, | |
new Type[] { | |
typeof(IPublishedContent), | |
typeof(Action<ConvertingTypeEventArgs>), | |
typeof(Action<ConvertedTypeEventArgs>), | |
typeof(CultureInfo) }, | |
null); | |
if (typeof(IEnumerable<IPublishedContent>).IsAssignableFrom(value.GetType())) | |
{ | |
// get type of objects to be returned in the collection | |
Type outputItemType = context.PropertyDescriptor.PropertyType.GenericTypeArguments[0]; | |
// create a list for the output collection | |
object outputList = Activator.CreateInstance(typeof(List<>).MakeGenericType(outputItemType)); | |
foreach (IPublishedContent inputItem in (IEnumerable<IPublishedContent>)value) | |
{ | |
((IList)outputList).Add( | |
dittoAs | |
.MakeGenericMethod(new[] { outputItemType }) | |
.Invoke(null, new[] { inputItem, null, null, null }) | |
); | |
} | |
return outputList; | |
} | |
else if(typeof(IPublishedContent).IsAssignableFrom(value.GetType())) | |
{ | |
return dittoAs | |
.MakeGenericMethod(new[] { context.PropertyDescriptor.PropertyType }) | |
.Invoke(null, new[] { value, null, null, null }); | |
} | |
return null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment