我想用一个字符串访问一个动态c#属性的值:

动态d = new {value1 = "some", value2 = "random", value3 = "value"};

如果我只有“value2”作为字符串,我如何才能得到d.value2(“random”)的值?在javascript中,我可以做d["value2"]来访问值("random"),但我不确定如何用c#和反射来做到这一点。我最接近的说法是:

“value2”d.GetType () . getproperty()……但我不知道如何从中获得实际价值。

一如既往,谢谢你的帮助!


当前回答

一些解决方案不是工作的valuekind对象,我从一个json字符串获得的,也许是因为我没有一个具体的类型在我的代码,类似于对象,我将从json字符串获得,所以我是如何去做的

JsonElement myObject = System.Text.Json.JsonSerializer.Deserialize<JsonElement>(jsonStringRepresentationOfMyObject);

/*In this case I know that there is a property with 
the name Code, otherwise use TryGetProperty. This will 
still return a JsonElement*/

JsonElement propertyCode = myObject.GetProperty("Code");
        
/*Now with the JsonElement that represents the property, 
you can use several methods to retrieve the actual value, 
in this case I know that the value in the property is a string, 
so I use the GetString method on the object. If I knew the value 
was a double, then I would use the GetDouble() method on the object*/

string code = propertyCode.GetString();

这对我很有用

其他回答

一些解决方案不是工作的valuekind对象,我从一个json字符串获得的,也许是因为我没有一个具体的类型在我的代码,类似于对象,我将从json字符串获得,所以我是如何去做的

JsonElement myObject = System.Text.Json.JsonSerializer.Deserialize<JsonElement>(jsonStringRepresentationOfMyObject);

/*In this case I know that there is a property with 
the name Code, otherwise use TryGetProperty. This will 
still return a JsonElement*/

JsonElement propertyCode = myObject.GetProperty("Code");
        
/*Now with the JsonElement that represents the property, 
you can use several methods to retrieve the actual value, 
in this case I know that the value in the property is a string, 
so I use the GetString method on the object. If I knew the value 
was a double, then I would use the GetDouble() method on the object*/

string code = propertyCode.GetString();

这对我很有用

从动态文档中获取属性 当.GetType()返回null时,尝试这样做:

var keyValuePairs = ((System.Collections.Generic.IDictionary<string, object>)doc);
var val = keyValuePairs["propertyName"].ToObject<YourModel>;

这是我得到一个动态的属性值的方法:

    public dynamic Post(dynamic value)
    {            
        try
        {
            if (value != null)
            {
                var valorCampos = "";

                foreach (Newtonsoft.Json.Linq.JProperty item in value)
                {
                    if (item.Name == "valorCampo")//property name
                        valorCampos = item.Value.ToString();
                }                                           

            }
        }
        catch (Exception ex)
        {

        }


    }

如果你有一个动态变量,例如DapperRow,你可以先构建一个ExpandoObject,然后将Expando转换为一个IDictionary<string对象>。从那时起,可以通过属性名获取值。

帮助方法ToExpandoObject:

public static ExpandoObject ToExpandoObject(object value)
    {
        IDictionary<string, object> dapperRowProperties = value as IDictionary<string, object>;
        IDictionary<string, object> expando = new ExpandoObject();
        if (dapperRowProperties == null)
        {
            return expando as ExpandoObject;
        }
        foreach (KeyValuePair<string, object> property in dapperRowProperties)
        {
            if (!expando.ContainsKey(property.Key))
            {
                expando.Add(property.Key, property.Value);
            }
            else
            {
                //prefix the colliding key with a random guid suffixed 
                expando.Add(property.Key + Guid.NewGuid().ToString("N"), property.Value);
            } 
        }
        return expando as ExpandoObject;
    }

示例用法,我用粗体标记了赋予我们访问权限的类型转换,我用**字母标记了重要的位:

  using (var transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
        {
            foreach (var dynamicParametersForItem in dynamicParametersForItems)
            {
                var idsAfterInsertion = (await connection.QueryAsync<object>(sql, dynamicParametersForItem)).ToList();
                if (idsAfterInsertion != null && idsAfterInsertion.Any())
                {
                    **var idAfterInsertionDict = (IDictionary<string, object>) ToExpandoObject(idsAfterInsertion.First());**
                    string firstColumnKey = columnKeys.Select(c => c.Key).First();
                    **object idAfterInsertionValue = idAfterInsertionDict[firstColumnKey];**
                    addedIds.Add(idAfterInsertionValue); //we do not support compound keys, only items with one key column. Perhaps later versions will return multiple ids per inserted row for compound keys, this must be tested.
                }
            }
        }

在我的示例中,我在动态对象DapperRow中查找一个属性值,并首先将Dapper行转换为ExpandoObject,并将其转换为一个字典属性包,如本文的其他回答中所示和提到的那样。

我的示例代码是我正在工作的Dapper扩展的InsertMany方法,我想在批量插入后抓住这里的多个id。

public static object GetProperty(object target, string name)
{
    var site = System.Runtime.CompilerServices.CallSite<Func<System.Runtime.CompilerServices.CallSite, object, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, name, target.GetType(), new[]{Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(0,null)}));
    return site.Target(site, target);
}

添加对Microsoft.CSharp的引用。也适用于动态类型和私有属性和字段。

编辑:虽然这种方法是有效的,但是从Microsoft.VisualBasic.dll程序集中可以找到几乎快20倍的方法:

public static object GetProperty(object target, string name)
{
    return Microsoft.VisualBasic.CompilerServices.Versioned.CallByName(target, name, CallType.Get);
}