Anders Hattestad
Jun 13, 2010
visibility 10936
star star star star star
(0 votes)

How to actually make all PropertyData save in the Dynamic Data Store

Mr Smith had a blog post about how to save CMS Properties in the Dynamic Data Store. So I started to implement it. You can make yourself a save method for one class but not all classes that inherit form one class. (I can understand that). You therefore have to find all classes that inherit from PropertyData to explicit set the save method for that class.

Its not hard, but as always when you do stuff you stumble upon private methods :). And this time it was in the GetTypes() in AssemblyTypeInfo.

I therefore made myself this hack

public static class InternalHacks
{
    public static Type[] GetTypes(this AssemblyTypeInfo item)
    {
        var info = typeof(AssemblyTypeInfo).GetMethod("GetTypes", System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.NonPublic);
        if (info != null)
        {
            object result=info.Invoke(item, new object[] { });
            return result as Type[];
        }
        return null;
    }

First of all I needet to register my save method in each of the PropertyData classes.

public class AttachEvents : PlugIn.PlugInAttribute
{
    public static void Start()
    {
        foreach (AssemblyTypeInfo info in PlugInLocator.Assemblies.Values)
            foreach (Type type in info.GetTypes())
                if (type.IsSubclassOf(typeof(PropertyData)))
                    GlobalTypeHandlers.Instance.Add(type, new PropertyDataHandlere(type));
    }
}

(I know, there is a new attribute you could use, but old habits :))

Then I made myself a save method class like this:

class PropertyDataHandlere : ITypeHandler
{
    Type T;
    public PropertyDataHandlere(Type t)
    {
        T = t;
    }
    public PropertyData MakeObject()
    {
        return Activator.CreateInstance(T) as PropertyData;
    }
    PropertyData propertyInstance;
    public PropertyData PropertyInstance
    {
        get
        {
            if (propertyInstance == null)
                propertyInstance = MakeObject();
            return propertyInstance;
        }
    }
    public Type MapToDatabaseType(Type type)
    {
        switch (PropertyInstance.Type)
        {
            case PropertyDataType.Boolean:
                return typeof(Boolean);
            case PropertyDataType.Date:
                return typeof(DateTime);
            case PropertyDataType.FloatNumber:
                return typeof(double);
            case PropertyDataType.Number:
                return typeof(int);
            case PropertyDataType.String:
                return typeof(string);
            default:
                return typeof(string);
        }


    }

    public object ToDatabaseFormat(string propertyName, object propertyValue, Type ownerType)
    {
        PropertyData prop = propertyValue as PropertyData;
        switch (PropertyInstance.Type)
        {
            case PropertyDataType.Boolean:
                return (bool)prop.Value;
            case PropertyDataType.Date:
                return (DateTime)prop.Value;
            case PropertyDataType.FloatNumber:
                return (double)prop.Value;
            case PropertyDataType.Number:
                return (int)prop.Value;

            default:
                return prop.ToString();
        }
    }

    public object FromDatabaseFormat(string propertyName, object propertyValue, Type targetType, Type ownerType)
    {
        PropertyData result = MakeObject();
        switch (PropertyInstance.Type)
        {
            case PropertyDataType.Boolean:
                result.Value = propertyValue;
                break;
            case PropertyDataType.Date:
                result.Value = propertyValue;
                break;
            case PropertyDataType.FloatNumber:
                result.Value = propertyValue;
                break;
            case PropertyDataType.Number:
                result.Value = propertyValue;
                break;
            case PropertyDataType.String:
                result.ParseToSelf(propertyValue as string);
                break;
            default:
                return null;

        }
        return result;
    }
}

And this is it. When you now try to save this class

public class TestClass1
{
    public TestClass1()
    {
        Text2 = new PropertyString();
        Text3 = new PropertyXhtmlString();
        Tall2 = new PropertyNumber();
        Tall4 = new PropertyFloatNumber();
        Date3 = new PropertyDate();
        PageRef2 = new PropertyPageReference();
    }
    public string Text1 { get; set; }
    public PropertyString Text2 { get; set; }
    public PropertyXhtmlString Text3 { get; set; }

    public int? Tall1 { get; set; }
    public PropertyNumber Tall2 { get; set; }

    public float? Tall3 { get; set; }
    public PropertyFloatNumber Tall4 { get; set; }

    public DateTime Date1 { get; set; }
    public DateTime? Date2 { get; set; }
    public PropertyDate Date3 { get; set; }

    public PageReference PageRef1 { get; set; }
    public PropertyPageReference PageRef2 { get; set; }
}

It will save as :

  • Date1[System.DateTime]=Inline
  • Date2[System.Nullable`1[System.DateTime]]=Inline
  • Date3[EPiServer.Core.PropertyDate]=Inline
  • PageRef1[EPiServer.Core.PageReference]=Inline
  • PageRef2[EPiServer.Core.PropertyPageReference]=Inline
  • Tall1[System.Nullable`1[System.Int32]]=Inline
  • Tall2[EPiServer.Core.PropertyNumber]=Inline
  • Tall3[System.Nullable`1[System.Single]]=Inline
  • Tall4[EPiServer.Core.PropertyFloatNumber]=Inline
  • Text1[System.String]=Inline
  • Text2[EPiServer.Core.PropertyString]=Inline
  • Text3[EPiServer.SpecializedProperties.PropertyXhtmlString =Inline
  • Jun 13, 2010

    Comments

    Sep 21, 2010 10:33 AM

    Nice one Anders
    / Paul Smith

    Sep 21, 2010 10:33 AM

    Thanks Mr Smith :)
    / Anders Hattestad

    error Please login to comment.
    Latest blogs
    Exploring Asset Lifecycle Management Approaches for Bynder and Optimizely SaaS CMS

    Note: This is Part 3 of our Bynder integration series. For setup and filtering prerequisites, see Part 1  and  Part 2 . Introduction In my previous...

    Vipin Banka | Jul 5, 2026

    Unlock AI-Ready Experiences with Optimizely

    Over the past few months, almost every customer conversation has shifted from SEO to AI readiness. The questions are no longer just: “How do we......

    Madhu | Jul 5, 2026 |

    Planning Your Bynder DAM and Optimizely SaaS CMS Integration the Right Way: Avoiding Asset Sprawl and Unnecessary Synchronization

    Note: This is Part 2 of our Bynder integration series. If you missed the Part 1, check out " Implementing the Bynder DAM Connector with Optimizely...

    Vipin Banka | Jul 4, 2026

    Implementing the Bynder DAM Connector with Optimizely SaaS CMS: Lessons Learned

    What I learned while integrating Bynder DAM with Optimizely SaaS CMS, exploring Optimizely Graph, and building a headless frontend experience....

    Vipin Banka | Jul 3, 2026

    Optimizely London developer meetup 2026: a round up

    Well, what can I say? Last night we wrapped up! Yet another London Developer Meetup, hosted at the superb Lightwell venue And this is also a...

    Scott Reed | Jul 3, 2026

    AvantiBit Custom Settings for Optimizely CMS

    AvantiBit Custom Settings is a free, Apache-2.0 Optimizely CMS add-on for typed, site- and language-aware configuration that stays out of content...

    Enes Bajramovic | Jul 3, 2026 |