【问题标题】:Dynamically Add C# Properties at Runtime在运行时动态添加 C# 属性
【发布时间】:2013-03-27 00:43:00
【问题描述】:

我知道有一些问题可以解决这个问题,但答案通常遵循推荐字典或参数集合的思路,这在我的情况下不起作用。

我正在使用一个通过反射工作的库来对具有属性的对象做很多聪明的事情。这适用于已定义的类以及动态类。我需要更进一步,并按照以下方式做一些事情:

public static object GetDynamicObject(Dictionary<string,object> properties) {
    var myObject = new object();
    foreach (var property in properties) {
        //This next line obviously doesn't work... 
        myObject.AddProperty(property.Key,property.Value);
    }
    return myObject;
}

public void Main() {
    var properties = new Dictionary<string,object>();
    properties.Add("Property1",aCustomClassInstance);
    properties.Add("Property2","TestString2");

    var myObject = GetDynamicObject(properties);

    //Then use them like this (or rather the plug in uses them through reflection)
    var customClass = myObject.Property1;
    var myString = myObject.Property2;

}

该库适用于动态变量类型,并手动分配属性。但是我不知道会预先添加多少或哪些属性。

【问题讨论】:

    标签: c# dynamic reflection properties


    【解决方案1】:

    你看过 ExpandoObject 吗?

    见:http://blogs.msdn.com/b/csharpfaq/archive/2009/10/01/dynamic-in-c-4-0-introducing-the-expandoobject.aspx

    来自 MSDN:

    ExpandoObject 类使您能够在运行时添加和删除其实例的成员,还可以设置和获取这些成员的值。此类支持动态绑定,这使您可以使用像 sampleObject.sampleMember 这样的标准语法,而不是像 sampleObject.GetAttribute("sampleMember") 这样更复杂的语法。

    允许您做一些很酷的事情,例如:

    dynamic dynObject = new ExpandoObject();
    dynObject.SomeDynamicProperty = "Hello!";
    dynObject.SomeDynamicAction = (msg) =>
        {
            Console.WriteLine(msg);
        };
    
    dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty);
    

    根据您的实际代码,您可能更感兴趣:

    public static dynamic GetDynamicObject(Dictionary<string, object> properties)
    {
        return new MyDynObject(properties);
    }
    
    public sealed class MyDynObject : DynamicObject
    {
        private readonly Dictionary<string, object> _properties;
    
        public MyDynObject(Dictionary<string, object> properties)
        {
            _properties = properties;
        }
    
        public override IEnumerable<string> GetDynamicMemberNames()
        {
            return _properties.Keys;
        }
    
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (_properties.ContainsKey(binder.Name))
            {
                result = _properties[binder.Name];
                return true;
            }
            else
            {
                result = null;
                return false;
            }
        }
    
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            if (_properties.ContainsKey(binder.Name))
            {
                _properties[binder.Name] = value;
                return true;
            }
            else
            {
                return false;
            }
        }
    }
    

    这样你只需要:

    var dyn = GetDynamicObject(new Dictionary<string, object>()
        {
            {"prop1", 12},
        });
    
    Console.WriteLine(dyn.prop1);
    dyn.prop1 = 150;
    

    从 DynamicObject 派生允许您提出自己的策略来处理这些动态成员请求,注意这里有怪物:编译器将能够验证很多动态调用,你不会得到智能感知,所以请记住这一点。

    【讨论】:

      【解决方案2】:

      感谢@Clint 的精彩回答:

      只是想强调使用 Expando 对象解决这个问题是多么容易:

      var dynamicObject = new ExpandoObject() as IDictionary<string, Object>;
      foreach (var property in properties) {
          dynamicObject.Add(property.Key,property.Value);
      }      
      

      【讨论】:

      • 这里的属性是什么“foreach(属性中的var属性)”例如我有一个学生班级,我想根据我的 JSON 响应添加属性
      • @singhswat 它是Dictionary&lt;string, object&gt;(基于问题中的代码)。
      【解决方案3】:

      您可以将您的 json 字符串反序列化为字典,然后添加新属性然后对其进行序列化。

      var jsonString = @"{}";
      
      var jsonDoc = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString);
      
      jsonDoc.Add("Name", "Khurshid Ali");
      
      Console.WriteLine(JsonSerializer.Serialize(jsonDoc));
      

      【讨论】:

        猜你喜欢
        • 2017-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-04
        • 2012-11-18
        • 2012-09-16
        • 1970-01-01
        • 2015-12-12
        相关资源
        最近更新 更多