Получить значение динамического свойства С# через строку

Я хотел бы получить доступ к значению свойства dynamic С# со строкой:

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

Как я могу получить значение d.value2 ( "random" ), если у меня есть только "value2" в виде строки? В javascript я мог бы сделать d [ "value2" ] для доступа к значению ( "случайный" ), но я не уверен, как это сделать с помощью С# и отражения. Самое близкое, что я пришел, это:

d.GetType().GetProperty("value2")... но я не знаю, как получить от него фактическое значение.

Как всегда, спасибо за вашу помощь!

Ответ 1

Как только у вас есть PropertyInfo (от GetProperty), вам нужно позвонить GetValue и передать экземпляр, из которого вы хотите получить значение. В вашем случае:

d.GetType().GetProperty("value2").GetValue(d, null);

Ответ 2

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

Ответ 3

Dynamitey - это библиотека .net std с открытым исходным кодом, которая позволяет вам называть ее как ключевое слово dynamic, но используя строку для имени свойства, а не компилятор, который делает это за вас, и в итоге она становится равной отражению по скорости (что не так быстро, как использование динамического ключевого слова, но это связано с дополнительными издержками динамического кэширования, когда компилятор статически кэширует).

Dynamic.InvokeGet(d,"value2");

Ответ 4

Самый простой способ получения как в setter и getter для имущества, которое работает для любого типа, включая dynamic и ExpandoObject является использование 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");

Ответ 5

В большинстве случаев, когда вы запрашиваете динамический объект, вы получаете ExpandoObject (не в вопросе анонимного, но статически типизированного примера выше, но вы упомянете JavaScript и мой выбранный JSON-анализатор JsonFx, например, генерирует ExpandoObjects).

Если ваша динамика на самом деле является ExpandoObject, вы можете избежать отражения, отбросив ее в IDictionary, как описано в http://msdn.microsoft.com/en-gb/library/system.dynamic.expandoobject.aspx.

После того, как вы передали IDictionary, у вас есть доступ к полезным методам, например .Item и .ContainsKey

Ответ 6

d.GetType(). GetProperty ( "значение2" )

возвращает объект PropertyInfo.

Итак, тогда

propertyInfo.GetValue(d)

Ответ 7

Так я получил значение свойства dinamic:

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

        }


    }

Ответ 8

GetProperty/GetValue не работает для данных Json, он всегда генерирует нулевое исключение, однако вы можете попробовать этот подход:

Сериализовать свой объект с помощью JsonConvert:

var z = Newtonsoft.Json.JsonConvert.DeserializeObject(Convert.ToString(request));

Затем перейдите к нему напрямую, вернув его в строку:

var pn = (string)z["DynamicFieldName"];

Он может работать прямо, применяя Convert.ToString(запрос) [ "DynamicFieldName" ], однако я не тестировал.

Ответ 9

Чтобы получить свойства из динамического документа, когда .GetType() возвращает null, попробуйте это:

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