Frage

Ist C # etwas wie Python __getattr__ haben?

Ich habe eine Klasse mit vielen Eigenschaften, und sie alle den gleichen Zugriffscode teilen. Ich möchte in der Lage sein, die einzelnen Accessoren ganz fallen zu lassen, so wie in Python.

Hier ist, was mein Code sieht aus wie jetzt:

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

Und hier ist das, was ich möchte:

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

Gibt es eine Möglichkeit, dies in C # zu erreichen, ohne Aufruf Get direkt?

Danke,

War es hilfreich?

Lösung

Nein. Obwohl C # Reflektion unterstützt, ist es schreibgeschützt (für bestückte Baugruppen). Das heißt, Sie können keine Methoden, Eigenschaften ändern, oder andere Metadaten. Obwohl Sie eine dynamische Eigenschaft zu schaffen, nannte es nicht wäre sehr bequem - es wäre noch schlimmer als Ihre Get Methode. Abgesehen von einer Dictionary<string, object> verwenden und einen Indexer für die Klasse, gibt es nicht viel, was Sie tun können. Wie auch immer, ist ein Wörterbuch nicht besser tun, wenn Sie, dass viele Eigenschaften?

Python prüft nicht, ob ein Attribut existiert bei „kompilieren-time“ (oder zumindest der Ladezeit). C # tut. Das ist ein fundamentaler Unterschied zwischen den beiden Sprachen. In Python können Sie tun:

class my_class:
    pass

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

In C # würden Sie nicht in der Lage sein, das zu tun, weil C # überprüft eigentlich, wenn der Name my_attr zur Compile-Zeit vorhanden ist.

Andere Tipps

Ich bin nicht sicher, aber vielleicht die dynamischen Funktionen der Version 4.0 werden Ihnen dabei helfen. Sie werden allerdings warten müssen ...

Darf ich fragen: Warum nicht möchten, dass Sie die einzelnen Eigenschaften? Das ist der idiomatische .NET Weg, um die Daten zu exprimieren mit einem Objekt zugeordnet ist.

persönlich die Daten unter der Annahme nicht spärlich ist, würde ich die Eigenschaften behalten und die allgemeine Methode Gebrauch Reflexion haben - dies kompilierten Code machen, so schnell wie möglich:

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

Natürlich, wenn Sie nicht über die Eigenschaften kümmern sich selbst definiert, dann durch eine Indexer und Lookup (wie Wörterbuch) wäre in Ordnung sein. Es gibt auch Dinge, die Sie mit Postsharp zu tun könnte der Lage sein, eine Reihe von Eigenschaften in einem Objekt-Tasche zu drehen -. Wahrscheinlich nicht wert, obwohl

Wenn Sie die Eigenschaften für Datenbindung und Runtime-Entdeckung wollen, aber kann sie nicht zur Compile-Zeit definieren, dann würden Sie bei dynamischen Typdeskriptoren aussehen müssen; entweder ICustomTypeDescriptor oder TypeDescriptionProvider -. ein gutes Stück Arbeit, aber sehr vielseitig (lassen Sie mich wissen, wenn Sie weitere Informationen wünschen)

Dies ist nicht das gleiche wie das, was Sie in Python mit dynamischen Eigenschaftsnamen, aber man könnte es nützlich sein:

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;
                }
            }
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top