Pergunta

A C # tem nada parecido __getattr__ do Python?

Eu tenho uma classe com muitas propriedades, e todos eles compartilham o mesmo código de assessor. Eu gostaria de ser capaz de soltar os assessores individuais inteiramente, assim como em Python.

Aqui está o que minha aparência código como agora:

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

E aqui está o que eu gostaria:

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 alguma maneira de conseguir isso em C # sem chamar Get diretamente?

Obrigado,

Foi útil?

Solução

No. Embora C # suportes reflexão, que é apenas de leitura (para os conjuntos carregados). Isso significa que você não pode alterar quaisquer métodos, propriedades ou qualquer outro metadados. Embora você poderia criar uma propriedade dinâmica , chamando não seria muito conveniente - seria ainda pior do que usar o método Get. Além de usar um Dictionary<string, object> e um indexador para a sua classe, não há muito mais você pode fazer. De qualquer forma, não está fazendo um dicionário melhor se você tiver que muitas propriedades?

Python não verifica se um atributo existe em "tempo de compilação" (ou, pelo menos, carga-time). C # faz. Essa é uma diferença fundamental entre as duas línguas. Em Python você pode fazer:

class my_class:
    pass

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

Em C # você não seria capaz de fazer isso porque C # realmente verifica se o nome my_attr existe em tempo de compilação.

Outras dicas

Eu não tenho certeza, mas talvez a dinâmica características da versão 4.0 irá ajudá-lo com isso. Você vai ter que esperar embora ...

Posso perguntar: por que você não quer que as propriedades individuais? Essa é a maneira .NET idiomática de expressar os dados associados a um objeto.

Pessoalmente, assumindo que os dados não é esparsa, eu iria manter as propriedades e têm o uso do método reflexão global - o que irá fazer o seu código compilado o mais rápido possível:

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

É claro, se você não se preocupam com as propriedades-se a ser definidas, em seguida, um indexador e pesquisa (como o dicionário) seria OK. Há também coisas que você pode ser capaz de fazer com PostSharp para transformar um conjunto de propriedades em uma propriedade-bag -. Provavelmente não vale a pena, embora

Se você quiser as propriedades disponíveis para os dados de ligação e descoberta de tempo de execução, mas não pode defini-los em tempo de compilação, então você precisa olhar para os descritores de tipo dinâmico; quer ICustomTypeDescriptor ou TypeDescriptionProvider -. um pouco de trabalho, mas muito versátil (deixe-me saber se você quiser mais informações)

Esta não é a mesma coisa que você entrar em Python com nomes de propriedades dinâmico, mas você pode achar que é útil:

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;
                }
            }
        }
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top