【问题标题】:Get property value from C# dynamic object by string (reflection?)通过字符串从 C# 动态对象中获取属性值(反射?)
【发布时间】:2012-01-27 17:28:12
【问题描述】:

假设我有一个动态变量:

dynamic d = *something*

现在,我为 d 创建属性,另一方面,我从字符串数组中获得了这些属性:

string[] strarray = { 'property1','property2',..... }

我事先不知道属性名称。

如何在代码中创建 d 并从 DB 中提取 strarray,我可以获取这些值吗?

我想得到d.property1 , d.property2

我看到该对象有一个 _dictionary 内部字典,其中包含键和值,我该如何检索它们?

【问题讨论】:

  • somethingIDynamicMetaObjectProvider 吗?
  • 在调试器中检查something的运行时类型并查看其公共成员。
  • 你能检查一下d.GetType()在运行时给你什么吗?
  • This SO answer 展示了如何检索动态属性。

标签: c# reflection .net-4.0


【解决方案1】:

我不知道动态创建对象是否有更优雅的方式,但使用普通的旧反射应该可以工作:

var nameOfProperty = "property1";
var propertyInfo = myObject.GetType().GetProperty(nameOfProperty);
var value = propertyInfo.GetValue(myObject, null);

如果myObject 的类型不包含同名的公共属性,GetProperty 将返回null


编辑:如果对象不是“常规”对象而是实现IDynamicMetaObjectProvider 的对象,则此方法将不起作用。请改为查看此问题:

【讨论】:

    【解决方案2】:

    这将为您提供动态变量中定义的所有属性名称和值。

    dynamic d = { // your code };
    object o = d;
    string[] propertyNames = o.GetType().GetProperties().Select(p => p.Name).ToArray();
    foreach (var prop in propertyNames)
    {
        object propValue = o.GetType().GetProperty(prop).GetValue(o, null);
    }
    

    【讨论】:

    • 这对我来说效果很好,我无法实现动态类型,谢谢
    • 只有在 d 是静态类型时才有效。如果 D 是 IDynamicMetaObjectProvider(例如 JObject),它会给您错误的属性。例如,如果 d = obj,那么它不会返回 'x',它将返回 JObject 的原始属性。 JObject obj = JObject.FromObject(new { x = 123 });
    【解决方案3】:

    希望对您有所帮助:

    public static object GetProperty(object o, string member)
    {
        if(o == null) throw new ArgumentNullException("o");
        if(member == null) throw new ArgumentNullException("member");
        Type scope = o.GetType();
        IDynamicMetaObjectProvider provider = o as IDynamicMetaObjectProvider;
        if(provider != null)
        {
            ParameterExpression param = Expression.Parameter(typeof(object));
            DynamicMetaObject mobj = provider.GetMetaObject(param);
            GetMemberBinder binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new CSharpArgumentInfo[]{CSharpArgumentInfo.Create(0, null)});
            DynamicMetaObject ret = mobj.BindGetMember(binder);
            BlockExpression final = Expression.Block(
                Expression.Label(CallSiteBinder.UpdateLabel),
                ret.Expression
            );
            LambdaExpression lambda = Expression.Lambda(final, param);
            Delegate del = lambda.Compile();
            return del.DynamicInvoke(o);
        }else{
            return o.GetType().GetProperty(member, BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
        }
    }
    

    【讨论】:

    • @Ewerton 已经有一段时间了,但我看到它使用 System.Linq.Expressions 将动态 getter 绑定到调用站点,并将编译留给 Lambda 表达式。我不知道我是从反编译代码中获取的,还是从其他地方获取的。
    • 你是大师!
    【解决方案4】:

    使用以下代码获取动态对象属性的名称和值。

    dynamic d = new { Property1= "Value1", Property2= "Value2"};
    
    var properties = d.GetType().GetProperties();
    foreach (var property in properties)
    {
        var PropertyName=property.Name; 
    //You get "Property1" as a result
    
      var PropetyValue=d.GetType().GetProperty(property.Name).GetValue(d, null); 
    //You get "Value1" as a result
    
    // you can use the PropertyName and Value here
     }
    

    【讨论】:

    • 仅当底层类型是普通对象时。它不适用于 PSObject 之类的包装器对象
    【解决方案5】:
    string json = w.JSON;
    
    var serializer = new JavaScriptSerializer();
    serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
    
    DynamicJsonConverter.DynamicJsonObject obj = 
          (DynamicJsonConverter.DynamicJsonObject)serializer.Deserialize(json, typeof(object));
    

    现在obj._Dictionary 包含一个字典。完美!

    此代码必须与 Deserialize JSON into C# dynamic object? + 在代码中将_dictionary 变量从“私有只读”变为公共

    【讨论】:

      【解决方案6】:

      你看到 ExpandoObject 类了吗?

      直接来自MSDN description:“表示一个对象,其成员可以在运行时动态添加和删除。”

      有了它,你可以编写如下代码:

      dynamic employee = new ExpandoObject();
      employee.Name = "John Smith";
      ((IDictionary<String, Object>)employee).Remove("Name");
      

      【讨论】:

      • 属性名称未知,所以这不起作用。
      • 代码有效(我在 Visual Studio 中检查过),因为员工实例是 ExpandoObject,因此可以在运行时添加和删除属性(如何在 MS 官方文档中解释)。这段代码完成了这个问题。
      • 还有ExpandoObject以外的其他动态对象,比如PSObject
      • 不,@ADIMO 没有。问题是如何访问动态对象的属性。但目前他不知道这些属性是什么。这些来自字符串数组。所以他需要通过名称查找属性,然后从属性中获取值
      【解决方案7】:

      如果 d 是由 Newtonsoft 创建的,您可以使用它来读取属性名称和值:

          foreach (JProperty property in d)
          {
              DoSomething(property.Name, property.Value);
          }
      

      【讨论】:

        【解决方案8】:

        使用属性(字符串)从动态对象中获取值数据。

        var nameOfProperty = "chairs";
        var propertyInfo = model.assets.GetType().GetField(nameOfProperty).GetValue(model.assets);
        

        【讨论】:

          【解决方案9】:

          认为这可能对将来的某人有所帮助。

          如果您已经知道属性名称,则可以执行以下操作:

          [HttpPost]
          [Route("myRoute")]
          public object SomeApiControllerMethod([FromBody] dynamic args){
             var stringValue = args.MyPropertyName.ToString();
             //do something with the string value.  If this is an int, we can int.Parse it, or if it's a string, we can just use it directly.
             //some more code here....
             return stringValue;
          }
          

          【讨论】:

          • 属性名称未知。
          【解决方案10】:

          您可以使用“dynamicObject.PropertyName.Value”直接获取动态属性的值。

          示例

          d.property11.Value
          

          【讨论】:

          • 问题是关于从动态对象中获取值,但他将属性名称作为字符串......例如他想做一些像我们在 Javascript 中所做的事情:obj["property1" ] 我相信这不是答案。
          【解决方案11】:

          你可以这样试试:

          d?.property1 , d?.property2
          

          我已经对其进行了测试并使用 .netcore 2.1

          【讨论】:

          • 问题是关于从动态对象中获取值,但他将属性名称作为字符串......例如他想做一些像我们在 Javascript 中所做的事情:obj["property1" ] 我相信这不是答案。
          猜你喜欢
          • 1970-01-01
          • 2023-03-30
          • 2010-11-02
          • 2010-11-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-12
          相关资源
          最近更新 更多