Question

Does C# have anything like Python's __getattr__?

I have a class with many properties, and they all share the same accessor code. I would like to be able to drop the individual accessors entirely, just like in Python.

Here's what my code looks like now:

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

And here's what I'd like:

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

Is there any way to achieve this in C# without calling Get directly?

Thanks,

Was it helpful?

Solution

No. Although C# supports reflection, it is read-only (for loaded assemblies). That means you can't change any methods, properties, or any other metadata. Although you could create a dynamic property, calling it wouldn't be very convenient - it would be even worse than using your Get method. Aside from using a Dictionary<string, object> and an indexer for your class, there's not much else you can do. Anyway, isn't doing a dictionary better if you have that many properties?

Python doesn't check if an attribute exists at "compile-time" (or at least load-time). C# does. That's a fundamental difference between the two languages. In Python you can do:

class my_class:
    pass

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

In C# you wouldn't be able to do that because C# actually checks if the name my_attr exists at compile-time.

OTHER TIPS

I'm not sure, but perhaps the dynamic features of version 4.0 will help you with that. You'll have to wait though...

Can I ask: why don't you want the individual properties? That is the idiomatic .NET way of expressing the data associated with an object.

Personally, assuming the data isn't sparse, I would keep the properties and have the overall method use reflection - this will make your compiled code as fast as 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);
    }

Of course, if you don't care about the properties themselves being defined, then an indexer and lookup (such as dictionary) would be OK. There are also things you might be able to do with postsharp to turn a set of properties into a property-bag - probably not worth it, though.

If you want the properties available for data-binding and runtime discovery, but can't define them at compile-time, then you would need to look at dynamic type descriptors; either ICustomTypeDescriptor or TypeDescriptionProvider - a fair bit of work, but very versatile (let me know if you want more info).

This is not the same as what you get in Python with dynamic property names, but you might find it useful:

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;
                }
            }
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top