Generate dynamic object from dictionary with C # Reflection

一曲冷凌霜 提交于 2019-12-05 07:08:34

If you've already got a dictionary, I'd avoid reflection and just use DynamicObject

For example:

public class DynamicDictionary : DynamicObject
{
    private readonly Dictionary<string, object> dictionary;

    public DynamicDictionary(Dictionary<string, object> dictionary)
    {
        this.dictionary = dictionary;
    }

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

    public override bool TrySetMember(
        SetMemberBinder binder, object value)
    {
        dictionary[binder.Name] = value;

        return true;
    }
}

Which can be used as follows:

dynamic x = new DynamicDictionary(
    new Dictionary<string, object> {{"Name", "Peter"}});

Console.WriteLine(x.Name);

I am not sure if this is what you're looking for, but judging by your question, I think you want to instantiate types at run time from the types located in a dictionary, which will be obtained by providing a key.

If that is so, then you can create the following class which will hold key-value pairs of strings which will be your keys, and Types which will represent your values which will be instantiated.

class DictionaryActivator
{
    Dictionary<string, Type> Dictionary = new Dictionary<string, Type>();

    public DictionaryActivator()
    {
        Dictionary.Add("MyCar", typeof(Car));
        Dictionary.Add("MyHouse", typeof(House));
        Dictionary.Add("MyFruit", typeof(Fruit));
        Dictionary.Add("MyComputer", typeof(Computer));
    }

    public T GetInstance<T>(string type, params object[] parameters)
    {
        if (parameters.Count() == 0)
        {
            return (T)Activator.CreateInstance(Dictionary[type]);
        }
        else
        {
            return (T)Activator.CreateInstance(Dictionary[type], parameters.ToArray());
        }
    }
}

You can also create four test classes to test this setup.

class House
{
    public int Number = 25;
}

class Car
{
    public double Price = 50000;
}

class Fruit
{
    public string Name = "Apple";
}

class Computer
{
    public string Cpu { get; set; }
    public string Gpu { get; set; }

    public Computer(string cpu, string gpu)
    {
        Cpu = cpu;
        Gpu = gpu;
    }
}

Once this is done, you can run the following lines of code to get all the types from the dictionary, instantiate them and cast them to appropriate types. As you might notice, the last Computer example is showing you how to add multiple parameters (in this case two) to the newly created instance and return it as an instance of type object.

In the end you can cast it to the Computer type so you can check that the constructor parameters actually went to the corresponding properties.

class Program
{
    static void Main()
    {
        var source = new DictionaryActivator();

        Console.WriteLine(source.GetInstance<Car>("MyCar").Price);
        Console.WriteLine(source.GetInstance<House>("MyHouse").Number);
        Console.WriteLine(source.GetInstance<Fruit>("MyFruit").Name);

        var computer = source.GetInstance<object>("MyComputer", "Fast CPU", "Fast GPU");

        Console.WriteLine((computer as Computer).Cpu);
        Console.WriteLine((computer as Computer).Gpu);

        Console.Read();
    }
}

Since ExpandoObject is a dictionary, you can use this extension function:

public static object With(this IDictionary<string, object> obj, IDictionary<string,object> additionalProperties)
{
  foreach (var name in additionalProperties.Keys)
    obj[name] = additionalProperties[name];
  return obj;
}

Usage:

var dynamicObj = new System.Dynamic.ExpandoObject().With(myDictionary);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!