通过字符串获取c#动态属性的值

Tim*_*Dog 173 c# dynamic

我想dynamic用字符串访问c#属性的值:

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

如果我只将"value2"作为字符串,我怎样才能获得d.value2("random")的值?在javascript中,我可以使用d ["value2"]来访问值("随机"),但我不知道如何使用c#和反射来执行此操作.我最接近的是:

d.GetType().GetProperty("value2") ......但我不知道如何从中获得实际价值.

一如既往,感谢您的帮助!

Ada*_*son 211

获得PropertyInfo(from GetProperty)之后,需要调用GetValue并传入要从中获取值的实例.在你的情况下:

d.GetType().GetProperty("value2").GetValue(d, null);
Run Code Online (Sandbox Code Playgroud)

  • -1.这仅适用于已转换为动态的简单.NET对象.它不适用于任何自定义动态对象,如Expando或ViewBag使用的ASP.NET MVC (14认同)
  • 这适用于Expando Object:(((IDictionary <string,object>)x))["value1"] (8认同)
  • 认为GetValue需要一个额外的参数 - egdGetType().GetProperty("value2").GetValue(d,null) (6认同)
  • 我得到了一个'd.GetType().GetProperty("value2").GetValue(d)'在监视窗口中抛出了类型'System.Reflection.TargetInvocationException'dynamic {System.Reflection.TargetInvocationException}`的异常接着就,随即..? (4认同)
  • 这是否适用于真正的动态ExpandoObject而不是匿名类型?由于`new {}`创建了一个具有已定义属性的真实匿名类型,因此调用GetType/GetProperty是有意义的,但是如果调用GetType,则会获得一个具有ExpandoObject属性的类型,但不一定是动态属性. (3认同)

Ill*_*ack 39

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);
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:虽然这种方法有效,但Microsoft.VisualBasic.dll程序集的方法快了近20倍:

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

  • 只是想提一下,VisualBasic版本不等同于原始的“ GetProperty”版本(GetProperty实际上调用了动态GetMember,即使在IronPython中的Python对象上也可以使用)。 (2认同)

jbt*_*ule 22

Dynamitey是一个开源.net std库,让你像dynamic关键字一样调用它,但是使用一个字符串作为属性名而不是编译器为你做的,它最终等于反射速度(这几乎没有那么快)使用动态关键字,但这是由于动态缓存的额外开销,编译器静态缓存).

Dynamic.InvokeGet(d,"value2");
Run Code Online (Sandbox Code Playgroud)


MaY*_*YaN 10

获取a setter和a getter属性的最简单方法,适用于任何类型,包括dynamicExpandoObject使用FastMember,这也是最快的方法(它使用Emit).

您可以TypeAccessor根据给定类型或ObjectAccessor基于给定类型的实例获取.

例:

var staticData = new Test { Id = 1, Name = "France" };
var objAccessor = ObjectAccessor.Create(staticData);
objAccessor["Id"].Should().Be(1);
objAccessor["Name"].Should().Be("France");

var anonymous = new { Id = 2, Name = "Hilton" };
objAccessor = ObjectAccessor.Create(anonymous);
objAccessor["Id"].Should().Be(2);
objAccessor["Name"].Should().Be("Hilton");

dynamic expando = new ExpandoObject();
expando.Id = 3;
expando.Name = "Monica";
objAccessor = ObjectAccessor.Create(expando);
objAccessor["Id"].Should().Be(3);
objAccessor["Name"].Should().Be("Monica");

var typeAccessor = TypeAccessor.Create(staticData.GetType());
typeAccessor[staticData, "Id"].Should().Be(1);
typeAccessor[staticData, "Name"].Should().Be("France");

typeAccessor = TypeAccessor.Create(anonymous.GetType());
typeAccessor[anonymous, "Id"].Should().Be(2);
typeAccessor[anonymous, "Name"].Should().Be("Hilton");

typeAccessor = TypeAccessor.Create(expando.GetType());
((int)typeAccessor[expando, "Id"]).Should().Be(3);
((string)typeAccessor[expando, "Name"]).Should().Be("Monica");
Run Code Online (Sandbox Code Playgroud)


小智 8

.GetType()要在return时从动态文档获取属性null,请尝试以下操作:

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


Fra*_*ton 7

在你要求动态对象的大部分时间里,你得到一个ExpandoObject(不是上面的问题的匿名但静态类型的例子,但是你提到了JavaScript和我选择的JSON解析器JsonFx,生成一个,生成ExpandoObjects).

如果您的动态实际上是ExpandoObject,则可以通过将其转换为IDictionary来避免反射,如http://msdn.microsoft.com/en-gb/library/system.dynamic.expandoobject.aspx中所述.

一旦转换为IDictionary,您就可以访问有用的方法,如.Item和.ContainsKey


Jam*_*unt 5

d.GetType().GetProperty("value2")

返回一个 PropertyInfo 对象。

那么做

propertyInfo.GetValue(d)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这是正确的答案,但如上所述,`GetValue(d)` 需要是 `GetValue(d,null)` (3认同)

小智 5

这是我获取动态属性值的方法:

    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)
        {

        }


    }
Run Code Online (Sandbox Code Playgroud)


And*_*son 5

GetProperty / GetValue不适用于Json数据,它始终生成null异常,但是,您可以尝试以下方法:

使用JsonConvert序列化您的对象:

var z = Newtonsoft.Json.JsonConvert.DeserializeObject(Convert.ToString(request));
Run Code Online (Sandbox Code Playgroud)

然后直接访问将其转换回字符串:

var pn = (string)z["DynamicFieldName"];
Run Code Online (Sandbox Code Playgroud)

它可能工作直施加Convert.ToString(请求)“DynamicFieldName”],但是我没有测试。

  • 此方法生成错误:错误 CS0021:无法将 [] 索引应用于“对象”类型的表达式。使用 `new JavaScriptSerializer().Deserialize&lt;object&gt;(json);` 以您建议的方式获取“属性” (2认同)