Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Nicholas Westby 2054 posts 7100 karma points c-trib
    Dec 21, 2015 @ 19:05
    Nicholas Westby
    0

    Can Ditto Map Polymorphic Collections?

    I was just reading this documentation about mapping collections with Ditto: http://umbraco-ditto.readthedocs.org/en/latest/usage-advanced-lists/

    It was recommending doing something like this for collections that may contain different types of instances:

    [TypeConverter(typeof(DittoPickerConverter))]
    public MyParentClass{
    
        // It is recommended to use lazy loading when referencing other IPublishedContent instances.
        [TypeConverter(typeof(DittoPickerConverter))]
        public virtual IEnumerable<IPublishedContent> Children {get; set;}
    }
    

    However, I'd like to avoid polluting my POCO's with IPublishedContent instances. Would something like this be possible with Ditto:

    // Class that has a property that is a collection of articles.
    [TypeConverter(typeof(ArticleConverter))]
    public class MyParentClass
    {
        [TypeConverter(typeof(ArticleConverter))]
        public virtual IEnumerable<IArticle> Articles {get; set;}
    }
    
    // Some classes that implement IArticle:
    public class NewsArticle: IArticle {/* Implements IArticle and add some more properties. */}
    public class PressReleaseArticle: IArticle {/* Implements IArticle and add some more properties. */}
    public class WalkthroughArticle: IArticle {/* Implements IArticle and add some more properties. */}
    

    My guess is that my converter would need to do something like this (i.e., it would have to be aware of each specific instance that implements IArticle):

    if ("NewsArticle".InvariantEquals(node.DocumentTypeAlias)) {
        return node.As<NewsArticle>();
    } else if ("PressReleaseArticle".InvariantEquals(node.DocumentTypeAlias)) {
        return node.As<PressReleaseArticle>();
    }
    

    Does that sound like it would be possible to do it that way? Is this the recommended way, or is there a more elegant way?

  • James Jackson-South 489 posts 1747 karma points c-trib
    Dec 22, 2015 @ 04:32
    James Jackson-South
    0

    Hi Nicholas,

    Unfortunately Ditto won't be able to do what you want.

    For conversion to be allowed we need to be able to created an instance of the type passed as the generic type parameter in order to map its properties. Since an IArticle instance cannot be created we are unable to do any mapping.

    I would use the method recommended in the documentation then separate the list and map based on DocTypeAlias when you need to.

    If you stored a retrievable dictionary of types somewhere keyed with type name you could do something like the following.

    IEnumerable<IArticle> articles = Model.Articles.Select(a => a.As(Cache.GetType(a.DocTypeAlias))).Cast<IArticle>(); 
    

    Umbraco has a method which allows you to retrieve all the types in your solution that inherit a base type. You could use that to populate your cache.

    IEnumerable<Type> registerTypes = PluginManager.Current.ResolveTypes<BaseType>();
    

    Hope that helps

    James

  • Nicholas Westby 2054 posts 7100 karma points c-trib
    Dec 28, 2015 @ 18:49
    Nicholas Westby
    0

    FYI, somebody else made this possible with Ditto and Archetype: https://github.com/micklaw/Ditto.Resolvers/issues/4

    This is how I use that:

    using Our.Umbraco.Ditto.Resolvers.Archetype.Attributes;
    using System.Collections.Generic;
    using Widgets;
    public class TypicalPage
    {
        [ArchetypeValueResolver(alias:"mainContent")]
        public List<IWidget> MainContent { get; set; }
    }
    

    The IWidget is just an empty interface, and here's what one of the widgets looks like:

    using Our.Umbraco.Ditto.Resolvers.Archetype.Attributes;
    [ArchetypeContent(alias: "RichText")]
    public class RichTextWidget : IWidget
    {
        [ArchetypeValueResolver(alias:"richText")]
        public string Text { get; set; }
    }
    

    Would be great if this pattern were also supported in the main Ditto package (i.e., polymorphic collections).

Please Sign in or register to post replies

Write your reply to:

Draft