Question

Est-ce que C # a quelque chose comme Python __getattr__?

J'ai une classe avec plusieurs propriétés et elles partagent toutes le même code d'accès. J'aimerais pouvoir supprimer complètement les accesseurs individuels, comme en Python.

Voici à quoi ressemble mon code:

class Foo
{
    protected bool Get(string name, bool def)
    {
        try {
            return client.Get(name);
        } catch {
            return def;
        }
    }

    public bool Bar
    {
        get { return Get("bar", true); }
        set { client.Set("bar", value); }
    }

    public bool Baz
    {
        get { return Get("baz", false); }
        set { client.Set("baz", value); }
    }
}

Et voici ce que je voudrais:

class Foo
{
    public bool Get(string name)
    {
        try {
            return client.Get(name);
        } catch {
            // Look-up default value in hash table and return it
        }
    }

    public void Set(string name, object value)
    {
        client.Set(name, value)
    }
}

Existe-t-il un moyen de réaliser cela en C # sans appeler Get directement?

Merci,

Était-ce utile?

La solution

Non. Bien que C # prenne en charge la réflexion, il est en lecture seule (pour les assemblys chargés). Cela signifie que vous ne pouvez modifier aucune méthode, propriété ou métadonnée. Bien que vous puissiez créer une propriété dynamique , l'appel ne serait pas très pratique - ce serait encore pire que d’utiliser votre méthode Get. En plus d'utiliser un Dictionary<string, object> et un indexeur pour votre classe, vous ne pouvez pas faire grand chose d'autre. Quoi qu’il en soit, faire un dictionnaire n’est-il pas préférable si vous avez autant de propriétés?

Python ne vérifie pas si un attribut existe à & "; au moment de la compilation &"; (ou au moins temps de chargement). C # fait. C'est une différence fondamentale entre les deux langues. En Python, vous pouvez faire:

class my_class:
    pass

my_instance = my_class()
my_instance.my_attr = 1
print(my_instance.my_attr)

En C #, vous ne pourriez pas le faire car C # vérifie si le nom my_attr existe au moment de la compilation.

Autres conseils

Je ne suis pas sûr, mais les fonctionnalités dynamiques de la version 4.0 vous aideront à cela. Vous devrez attendre cependant ...

Puis-je demander: pourquoi ne voulez-vous pas les propriétés individuelles? C’est la manière idiomatique .NET d’exprimer les données associées à un objet.

Personnellement, en supposant que les données ne soient pas rares, je conserverais les propriétés et demanderais à la méthode globale d’utiliser la réflexion - cela rendra le code compilé aussi vite que possible:

    protected T Get<T>(string name, T @default)
    {
        var prop = GetType().GetProperty(name);
        if(prop == null) return @default;
        return (T) prop.GetValue(this, null);
    }

Bien sûr, si vous ne vous souciez pas des propriétés elles-mêmes étant définies, un indexeur et une recherche (comme un dictionnaire) conviendraient. Il y a aussi des choses que vous pourriez faire avec postsharp pour transformer un ensemble de propriétés en un sac de propriétés, mais probablement pas la peine.

Si vous souhaitez que les propriétés soient disponibles pour la découverte de liaison de données et d'exécution, mais que vous ne puissiez pas les définir au moment de la compilation, vous devez examiner les descripteurs de type dynamique. ICustomTypeDescriptor ou TypeDescriptionProvider - un peu de travail, mais très polyvalent (faites-le moi savoir si vous souhaitez plus d’informations).

Ce n'est pas la même chose que ce que vous obtenez en Python avec des noms de propriétés dynamiques, mais cela pourrait vous être utile:

using System;
using System.Collections.Generic;

namespace Program
{
    class Program
    {
        static void Main(string[] args)
        {
            MyList<int> list = new MyList<int>();
            // Add a property with setter.
            list["One"] = 1;
            // Add a property with getter which takes default value.
            int two = list["Two", 2];
            Console.WriteLine("One={0}", list["One"]);
            Console.WriteLine("Two={0} / {1}", two, list["Two"]);
            try
            {
                Console.WriteLine("Three={0}", list["Three"]);
            }
            catch
            {
                Console.WriteLine("Three does not exist.");
            }
        }
        class MyList<T>
        {
            Dictionary<string, T> dictionary = new Dictionary<string,T>();

            internal T this[string property, T def]
            {
                get
                {
                    T value;
                    if (!dictionary.TryGetValue(property, out value))
                        dictionary.Add(property, value = def);
                    return value;
                }
            }
            internal T this[string property]
            {
                get
                {
                    return dictionary[property];
                }
                set
                {
                    dictionary[property] = value;
                }
            }
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top