-1

I have a list of key/values in following format

var temp = new Dictionary<string, string>();
temp["Prop1"] = "Test1";
temp["Prop2"] = "Test2";
temp["SubProperty.Sub1"] = "Test3";
temp["SubProperty.Sub2"] = "Test4";
temp["ListData[0].List1"] = "Test5";
temp["ListData[0].List2"] = "Test6";
temp["ListData[1].List1"] = "Test7";
temp["ListData[1].List2"] = "Test8";

Is there an easy way to convert this list int a new object such as below.

public class MainClass
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public SubClass SubProperty { get; set; }
    public ListClass[] ListData { get; set; }
}

public class ListClass
{
    public string List1 { get; set; }
    public string List2 { get; set; }
}

public class SubClass
{
    public string Sub1 { get; set; }
    public string Sub2 { get; set; }
}

I know ASP MVC does something like this, taking form names and values and auto parsing into instantiated property. But couldn't find what they use. Any help appreciated. Looking to either convert to class or even JSON would be useful and can convert to object that way

Danhol86
  • 1,352
  • 1
  • 11
  • 20
  • 1
    If, instead of just having a flat dictionary, you expressed that in JSON, you could just deserialize the JSON into the classes. Other than that, look up System.Reflection, and in particular, the PropertyInfo class. Given that you want to interpret something like `temp["ListData[1].List2"] = "Test8"`, it will be a lot of work – Flydog57 Nov 06 '20 at 15:12
  • Yea exactly. Wanted to avoid building my own interpreter in case something already exists I was unaware of. I don't have control of the intput data. Cheers – Danhol86 Nov 06 '20 at 15:22
  • @Flydog so my first thought on it was whether Newtonsoft could ser the dictionary to json then deser an object from it.. sadly it's not a hierarchical dictionary but a flattened thing in a custom way.. – Caius Jard Nov 06 '20 at 16:51
  • @danhol86 I don't think you'll find anything that serializes objects in that exact way; you'll probably have to get building – Caius Jard Nov 06 '20 at 16:53
  • See my answer. Seems to work ok for what I need. Did try the newtonsoft from dictionary, but didnt take into account ".". cheers for looking anyway – Danhol86 Nov 06 '20 at 16:56

1 Answers1

0

Created following using ExpandoObjects which seemed to do the trick for what I need. Will update if come accross any other scenarios

var temp = new Dictionary<string, string>();
temp["Prop1"] = "Test1";
temp["Prop2"] = "Test2";
temp["SubProperty.Sub1"] = "Test3";
temp["SubProperty.Sub2"] = "Test4";
temp["ListData[0].List1"] = "Test5";
temp["ListData[0].List2"] = "Test6";
temp["ListData[1].List1"] = "Test7";
temp["ListData[1].List2"] = "Test8";
temp["ListData[5].List1"] = "Test9";
temp["ListData[5].List2"] = "Test10";

var justjson = PropertiesToObject.ToJson(temp);
var myobj = PropertiesToObject.ToObject<MainClass>(temp);


public static class PropertiesToObject
{
    public static T ToObject<T>(Dictionary<string, string> dict)
    {
        var json = ToJson(dict);
        return JsonConvert.DeserializeObject<T>(json);
    }

    public static string ToJson(Dictionary<string, string> dict)
    {
        dynamic expando = new ExpandoObject();
        foreach (var item in dict)
        {
            AddProperty(expando, item.Key, item.Value);
        }

        return JsonConvert.SerializeObject(expando);
    }

    private static ExpandoObject SetValueIfListOrNot(ExpandoObject expando,string propertyName, object propertyValue)
    {
        bool isList = propertyName.Contains("[");
        var listName = propertyName.Split('[').FirstOrDefault();
        int listindex = isList ? int.Parse(propertyName.Split('[').LastOrDefault()?.Split(']').FirstOrDefault()) : 0;

        var expandoDict = expando as IDictionary<string, object>;
        if (expandoDict.ContainsKey(listName) == false)
        {
            if (!isList)
            {
                expandoDict.Add(listName, propertyValue);
            }
            else
            {
                var lobj = new dynamic[0];
                expandoDict.Add(listName, lobj);
            }
        }


        var exi = expandoDict[listName];
        if(exi.GetType().IsArray)
        {
            var ma = exi as dynamic[];
            var len = ma.Length;
            if (len < listindex + 1)
            {
                Array.Resize(ref ma, listindex + 1);
                expandoDict[listName] = ma;
            }

            var item = ma[listindex];
            if(item == null)
            {
                ma[listindex] = propertyValue;
            }
            return ma[listindex];
        } else
        {
            return exi as ExpandoObject;
        }
    }

    private static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
    {
        var subprops = propertyName.Split('.');
        var propname = subprops.First();

        var rest = string.Join(".", subprops.Skip(1).ToList());
        if (rest == "")
        {
            SetValueIfListOrNot(expando, propname, propertyValue);
        } else
        {
            var expa = SetValueIfListOrNot(expando, propname, new ExpandoObject());
            AddProperty(expa, rest, propertyValue);
        }
    }
}
Danhol86
  • 1,352
  • 1
  • 11
  • 20