ChatGPT解决这个技术问题 Extra ChatGPT

Get property value from C# dynamic object by string (reflection?)

Imagine that I have a dynamic variable:

dynamic d = *something*

Now, I create properties for d which I have on the other hand from a string array:

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

I don't know the property names in advance.

How in code, once d is created and strarray is pulled from DB, can I get the values?

I want to get d.property1 , d.property2.

I see that the object has a _dictionary internal dictionary that contains the keys and the values, how do I retrieve them?

Is something an IDynamicMetaObjectProvider?
Check the runtime type of something in the debugger and look at its public members.
Can you check what does d.GetType() give you in runtime?
This SO answer shows how to retrieve a dynamic property.
possible duplicate of Loop DynamicObject properties

C
Community

I don't know if there's a more elegant way with dynamically created objects, but using plain old reflection should work:

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

GetProperty will return null if the type of myObject does not contain a public property with this name.

EDIT: If the object is not a "regular" object but something implementing IDynamicMetaObjectProvider, this approach will not work. Please have a look at this question instead:

How do I reflect over the members of dynamic object?


T
Tomislav Markovski

This will give you all property names and values defined in your dynamic variable.

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

This worked beautifully for me, what i was not able to achieve for dynamic type, thanks
That only works if d is a static type. If D is a IDynamicMetaObjectProvider, (such as a JObject) it will give you the wrong properties. For example, if d = obj, then it won't return 'x', it will return the raw properties on JObject. JObject obj = JObject.FromObject(new { x = 123 });
I
IS4

Hope this would help you:

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 It's been quite a while, but I see it uses System.Linq.Expressions to bind the dynamic getter to a call site, and leaves the compiling to the LambdaExpression. I don't know if I took this from a decompiled code, or somewhere else.
You are a master!
J
JoDG

Use the following code to get Name and Value of a dynamic object's property.

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
 }

Only if the underlying type is a plain object. It won't work for wrapper objects like PSObject
C
Community
string json = w.JSON;

var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });

DynamicJsonConverter.DynamicJsonObject obj = 
      (DynamicJsonConverter.DynamicJsonObject)serializer.Deserialize(json, typeof(object));

Now obj._Dictionary contains a dictionary. Perfect!

This code must be used in conjunction with Deserialize JSON into C# dynamic object? + make the _dictionary variable from "private readonly" to public in the code there


A
ADIMO

Did you see ExpandoObject class?

Directly from MSDN description: "Represents an object whose members can be dynamically added and removed at run time."

With it you can write code like this:

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

The property names are not known so this will not work.
The code works (i checked it in visual studio) because the employee instance is an ExpandoObject so it's possibile add and remove property at runtime (how explained into the MS official documentation). This code accomplish the question.
There are other dynamic objects than ExpandoObject, like PSObject.
No @ADIMO it doesn't. The question is how to Access the property of an dynamic object. BUT at the moment he doesn't know what are the properties. Those are coming from a string array. So he needs to FIND THE PROPERTY IF IT EXISTS by name and THEN get the value from the property
u
user3285954

IF d was created by Newtonsoft you can use this to read property names and values:

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

R
Rajesh Kalavakunta

Getting value data from a dynamic objects using property(string).

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

c
cr1pto

Thought this might help someone in the future.

If you know the property name already, you can do something like the following:

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

The property names are not known.
S
Siggi Hergeirs

Say you have anonymous type in service result.Value, with class errorCode and property ErrorMessage, and needed to get the value of ErrorMessage, could get it in one-liner like this using dynamic:

var resVal = (dynamic)result.Value; var errMsg = resVal.GetType().GetProperty("errorCode").GetValue(resVal, null).ErrorMessage;


s
sajadre

you can try like this:

d?.property1 , d?.property2

I have tested it and working with .netcore 2.1


The question is talking about getting value from from dynamic object, but he has the property name as string ... for instance he want to do something like what we did in Javascript: obj["property1"] and i believe this is not an answer.