通过字符串从C#动态对象获取属性值(反射?)


76

假设我有一个动态变量:

dynamic d = *something*

现在,我d从字符串数组创建我拥有的属性:

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

我事先不知道属性名称。

d创建代码并将strarray从数据库中提取后,如何在代码中获取值?

我想得到d.property1 , d.property2

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


1
somethingIDynamicMetaObjectProvider
SLaks 2011年

something在调试器中检查的运行时类型,并查看其公共成员。
SLaks 2011年

1
您可以检查d.GetType()在运行时给您带来什么吗?
Tomislav Markovski

这样的答案显示了如何检索动态属性。
雷蒙·陈

Answers:


106

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

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

GetPropertynull如果类型myObject不包含具有此名称的公共属性,则将返回。


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


32

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

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

1
这对我来说效果很好,对于动态类型我无法实现,谢谢
Mrinal Kamboj 2016年

2
仅当d是静态类型时才有效。如果D是IDynamicMetaObjectProvider(例如JObject),它将为您提供错误的属性。例如,如果d = obj,则它将不返回“ x”,它将返回JObject上的原始属性。JObject obj = JObject.FromObject(new {x = 123});
Mike S

24

希望这对您有帮助:

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将动态吸气剂绑定到调用站点,并将编译留给LambdaExpression。我不知道我是从反编译代码中还是其他地方获取的。
IllidanS4在2015年

6

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

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
 }

1
仅当基础类型是普通对象时。它不适用于包装对象,例如PSObject
felixfbecker

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包含一本字典。完善!

此代码必须与反序列化JSON一起用于 C#动态对象中吗? +在其中的代码中将_dictionary变量从“专用只读”更改为公用


4

您看到ExpandoObject类了吗?

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

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

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

属性名称未知,因此将无法正常工作。
user3285954 '18

该代码有效(我在Visual Studio中对其进行了检查),因为员工实例是ExpandoObject,因此可以在运行时添加和删除属性(如何在MS官方文档中进行说明)。这段代码解决了这个问题。
ADIMO

还有其他的动态对象不是ExpandoObject一样PSObject
felixfbecker

不,@ ADIMO不是。问题是如何访问动态对象的属性。但是他现在不知道这些属性是什么。这些来自字符串数组。因此,他需要找到
有名

4

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

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

1

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

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

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

属性名称未知。
user3285954'2

0

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

范例

d.property11.Value

1
问题是关于从动态对象获取价值,但他的属性名称为字符串...例如,他想做一些类似于我们在Javascript中所做的事情:obj [“ property1”],我相信这不是回答。
bunjeeb

0

您可以这样尝试:

d?.property1 , d?.property2

我已经测试过并使用.netcore 2.1


1
问题是关于从动态对象获取价值,但他的属性名称为字符串...例如,他想做一些类似于我们在Javascript中所做的事情:obj [“ property1”],我相信这不是回答。
bunjeeb
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.