【问题标题】:Generate dynamic object from dictionary with C # Reflection使用 C# 反射从字典生成动态对象
【发布时间】:2013-08-19 21:29:13
【问题描述】:

我一直在研究C#中的反射,想知道如果我使用带有键值的字典可以创建一个带有变量的对象,该变量带有字典中每个键的名称及其值​​,那个字典的键值。

我有一个相反的方法,它从字典中提取一个对象,这个字典包含键和类属性及其值​​,属性的值。

如果可能的话,我想知道如何做到这一点。

下面是我的方法,它提取一个对象的字典:

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

【问题讨论】:

  • 你的意思是“动态”类型的对象吗?还是创建新类型?
  • 您使用什么版本的 .NET 框架?
  • 对象已经存在,退出这个函数时,我只需要将它的结果强制转换(myObject)到现有对象。 .NET 4.0
  • 可能这就是您要查找的内容 [Convert Dictionary To Anonymous Object?][1] [1]: stackoverflow.com/questions/7595416/…

标签: c# reflection system.reflection


【解决方案1】:

我不确定这是否是您正在寻找的,但从您的问题来看,我认为您想要 在运行时从位于字典中的类型实例化类型,这将通过提供一个键来获得。

如果是这样,那么您可以创建以下类,该类将保存作为您的键的字符串键值对和表示您将被实例化的值的类型。

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

您还可以创建四个测试类来测试此设置。

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

完成后,您可以运行以下代码行以从字典中获取所有类型,实例化它们并将它们转换为适当的类型。您可能会注意到,最后一个 Computer 示例向您展示了如何向新创建的实例添加多个参数(在本例中为两个)并将其作为 object类型的实例返回>.

最后你可以把它转换成Computer类型,这样你就可以检查构造函数参数是否真的去了相应的属性。

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

【讨论】:

  • 我可以创建一个 Object 类型的对象,并为其添加例如两个变量及其值并返回它?
  • 我已经编辑了我的答案,所以是的,你可以做到这一点。只需将所需数量的参数传递给新实例,然后使用 GetInstance(string, params object[]) 方法上定义的泛型类型将其转换为对象。
【解决方案2】:

如果你已经有了字典,我会避免反思,直接使用DynamicObject

例如:

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

可以如下使用:

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

Console.WriteLine(x.Name);

【讨论】:

    【解决方案3】:

    由于ExpandoObject是字典,你可以使用这个扩展函数:

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

    用法:

    var dynamicObj = new System.Dynamic.ExpandoObject().With(myDictionary);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-02
      • 1970-01-01
      • 2021-06-18
      • 1970-01-01
      • 2011-12-28
      • 2015-01-28
      • 2021-10-31
      • 1970-01-01
      相关资源
      最近更新 更多