1

I have written a method which creates a Dictionary. I need to convert this dictionary to a class.

Example of Dictionary

 Dictionary<string, dynamic> myDictionary = new Dictionary<string, dynamic> {
            { "ID1", 12 },
            { "ID2", "Text2"},
            { "ID3", "Text3" }
        };

and this is the sample of the class which needs to be created:

public class Foo
    {
        public int ID1 { get; set; }
        public string ID2 { get; set; }
        public string ID3 { get; set; }
    }
R.J. Dunnill
  • 2,049
  • 3
  • 10
  • 21
Ehsan Aliverdi
  • 143
  • 1
  • 1
  • 6
  • Looks like you've already created the class. What is your question? Do you not know how to retrieve values from a dictionary, not know how to assign values to an object's properties, or what? – John Wu Jun 17 '19 at 00:00
  • @JohnWu These are just samples. The Sample dictionary is created at runtime(I have no Idea about the Keys/ Type of them). During runtime, I need to create a class from that dictionary. – Ehsan Aliverdi Jun 17 '19 at 00:03
  • When you say "create a class", do you mean "create an instance of this class and populate its properties" or actually create a type with these properties? If the latter, then how would you use it in your program once it was created? – ProgrammingLlama Jun 17 '19 at 00:04
  • 2
    It is a truly unusual requirement for a program to be able to create a class at runtime. Bizarre, in fact. The point of classes (and types in general) is that they are used at compile time to ensure your program is structured properly. Perhaps you have an [xy problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – John Wu Jun 17 '19 at 00:04
  • No, I actually mean the Class Itself. Is it possible to convert a dictionary key to the class member at runtime? – Ehsan Aliverdi Jun 17 '19 at 00:12

2 Answers2

5

Your requirements are not clearly stated, but I'm guessing you are looking for a dymamic type that has properties whose names map to dictionary keys.

In that case you can use a simple dictionary wrapper like this one:

class DynamicDictionaryWrapper : DynamicObject
{
    protected readonly Dictionary<string,object> _source;

    public DynamicDictionaryWrapper(Dictionary<string,object> source)
    {
        _source = source;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = null;
        return (_source.TryGetValue(binder.Name, out result));
    }
}

Which you can use this way:

public static void Main()
{
    var myDictionary = new Dictionary<string, dynamic> {
        { "ID1", 12 },
        { "ID2", "Text2"},
        { "ID3", "Text3" }
    };  
    dynamic myObject = new DynamicDictionaryWrapper(myDictionary);

    Console.WriteLine(myObject.ID1);
    Console.WriteLine(myObject.ID2);
    Console.WriteLine(myObject.ID3);
}

Output:

12
Text2
Text3

Link to working example on DotNetFiddle

John Wu
  • 50,556
  • 8
  • 44
  • 80
4

As other people mentioned, this situation is very usual and definitely requires a context to solve it from a better perspective, as I suspect a bad architecture of the code base. Nonetheless, your question remains valid. To solve it, you have at least two possibilities:

1. Require development time; negligible time at runtime - Simply create a function that maps a given dictionary to an instance of your class. Example:

Foo MapDictionaryToFoo(IReadOnlyDictionary<string, dynamic> d)
{
    return new Foo
    {
        ID1 = d[nameof(Foo.ID1)],
        ID2 = d[nameof(Foo.ID2)],
        ID3 = d[nameof(Foo.ID3)]
    };
}

Example of call:

Foo myFoo = MapDictionaryToFoo(myDictionary);

2. Require runtime time; negligible development time - Create a function that maps a given dictionary to an arbitrary class, typically using Reflection. The example below assumes your class has a default constructor, therefore acting as a factory as well. If this is not the case, an existing instance can be passed in an additional parameter:

T CreateFromDictionary<T>(IReadOnlyDictionary<string, dynamic> d) where T : new()
{
    T obj = new T();

    foreach (var propertyInfo in typeof(T).GetProperties())
    {
        propertyInfo.SetValue(obj, d[propertyInfo.Name]);
    }

    return obj;
}

Example of call:

Foo myFoo = CreateFromDictionary<Foo>(myDictionary);

If I have to pick one, I would choose the first approach, as I avoid any Reflection, that is time consuming at runtime.

Jämes
  • 6,945
  • 4
  • 40
  • 56