Generate dynamic object from dictionary with C # R

2019-05-02 08:29发布

问题:

I've been researching a bit about reflections in C # and would like to know if I use a dictionary with keys-values ​​can create an object with the variable with the name of each key in the dictionary and their values​​, the key value of that dictionary.

I have a method that does the opposite, that extracts an object from a dictionary, this dictionary contains the keys and the class properties and their values​​, the value of the properties.

I wonder how to do this if possible.

Below is my method, which extracts a dictionary of an object:

protected Dictionary<String, String> getObjectProperty(object objeto)
{
    Dictionary<String, String> dictionary = new Dictionary<String, String>();

    Type type = objeto.GetType();
    FieldInfo[] field = type.GetFields();
    PropertyInfo[] myPropertyInfo = type.GetProperties();

    String value = null;

    foreach (var propertyInfo in myPropertyInfo)
    {
        if (propertyInfo.GetIndexParameters().Length == 0)
        {
            value = (string)propertyInfo.GetValue(objeto, null);
            value = value == null ? null : value;
            dictionary.Add(propertyInfo.Name.ToString(), value);
        }
    }

    return dictionary;
}

回答1:

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);


回答2:

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();
    }
}


回答3:

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);