web-dev-qa-db-fra.com

Obtenir la valeur de la propriété dynamique c # via une chaîne

J'aimerais accéder à la valeur d'une propriété dynamic c # avec une chaîne:

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

Comment puis-je obtenir la valeur de d.value2 ("random") si je n'ai que "valeur2" en tant que chaîne? En javascript, je pourrais faire d ["value2"] pour accéder à la valeur ("random"), mais je ne sais pas comment faire cela avec c # et la réflexion. Le plus proche que je suis venu est la suivante:

d.GetType().GetProperty("value2") ... mais je ne sais pas comment en tirer la valeur réelle.

Comme toujours, merci pour votre aide!

167
TimDog

Une fois que vous avez votre PropertyInfo (de GetProperty), vous devez appeler GetValue et transmettre l'instance dont vous voulez obtenir la valeur. Dans ton cas:

d.GetType().GetProperty("value2").GetValue(d, null);
201
Adam Robinson
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);
}

Ajouter une référence à Microsoft.CSharp. Fonctionne également pour les types dynamiques et les propriétés et champs privés.

Edit: Bien que cette approche fonctionne, il existe près de 20 × méthodes plus rapides de l'assembly Microsoft.VisualBasic.dll :

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

Dynamitey est une bibliothèque open source .net std, que vous pouvez appeler comme le mot clé dynamic, mais en utilisant une chaîne pour le nom de la propriété plutôt que le compilateur le faisant à votre place. , et cela finit par être égal à la réflexion speedwise (ce qui n’est pas aussi rapide que d’utiliser le mot-clé dynamic, mais cela est dû à la surcharge de la mise en cache dynamique, où le compilateur met en cache de manière statique).

Dynamic.InvokeGet(d,"value2");
22
jbtule

La méthode la plus simple pour obtenir un setter et un getter pour une propriété qui fonctionne pour tout type, y compris dynamic et ExpandoObject consiste à utiliser FastMember qui se trouve être la méthode la plus rapide autour de (utilise Emit).

Vous pouvez obtenir un TypeAccessor basé sur un type donné ou un ObjectAccessor basé sur une instance d'un type donné.

Exemple:

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");
8
MaYaN

La plupart du temps, lorsque vous demandez un objet dynamique, vous obtenez un ExpandoObject (pas dans l'exemple ci-dessus de type anonyme mais statiquement, mais vous mentionnez JavaScript et l'analyseur JSON choisi, JsonFx, génère ExpandoObjects).

Si votre dynamique est en fait un ExpandoObject, vous pouvez éviter les réflexions en le transmettant à IDictionary, comme décrit à l'adresse http://msdn.Microsoft.com/en-gb/library/system.dynamic .expandoobject.aspx .

Une fois que vous avez converti à IDictionary, vous avez accès à des méthodes utiles telles que .Item et .ContainsKey.

7
Francis Norton

d.GetType (). GetProperty ("valeur2")

renvoie un objet PropertyInfo.

Alors alors fais

propertyInfo.GetValue(d)
4
James Gaunt

GetProperty/GetValue ne fonctionne pas pour les données Json, il génère toujours une exception null. Toutefois, vous pouvez essayer cette approche:

Sérialisez votre objet en utilisant JsonConvert:

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

Puis accédez-y directement en le renvoyant à la chaîne:

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

Cela peut fonctionner directement en appliquant Convert.ToString (request) ["DynamicFieldName"], mais je n'ai pas encore testé.

4
Anderson

C’est ainsi que j’ai obtenu la valeur d’une propriété, propriété d’une dinamique:

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

        }


    }
4
Marcelo Lima Braga

Pour obtenir les propriétés d'un document dynamique lorsque .GetType() renvoie null, essayez ceci:

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