views:

354

answers:

4

Is there a way in C# to:

  1. Get all the properties of a class that have attributes on them (versus having to loop through all properties and then check if attribute exists.

  2. If i want all Public, Internal, and Protected properties but NOT private properties, i can't find a way of doing that. I can only do this:

    PropertyInfo[] props = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)

Is there a way to avoid getting private properties but do get everything else.

+1  A: 

I don't believe there's a way to do either of these.

Just how many types do you have to reflect over, though? Is it really a bottleneck? Are you able to cache the results to avoid having to do it more than once per type?

Jon Skeet
+1  A: 

In response to (2): If you're outside of the class/assembly in question, internal and protected are the same as private.

If you want to access these, you'll need to ask for all properties, as you've already done, and filter the list yourself.

Tim Robinson
+1  A: 

Regarding caching: if you access properties via TypeDescriptor.GetProperties then you get caching for free. The TypeDescriptor class has some other nice utility methods for reflection situations like this. It only operates on public properties though (no protected or internal members, and no fields).

Tim Robinson
The caching with TypeDescriptor is actually quite limited, partly because it has to deal with scenarios like extension properties.
Marc Gravell
+2  A: 

There isn't really a way to do it any quicker - but what you can do is do it less often by caching the data. A generic utility class can be a handy way of doing this, for example:

static class PropertyCache<T>
{
    private static SomeCacheType cache;
    public static SomeCacheType Cache
    {
        get
        {
            if (cache == null) Build();
            return cache;
        }
    }
    static void Build()
    {
        /// populate "cache"
    }
}

Then your PropertyCache.Cache has the data just for Foo, etc - with lazy population. You could also use a static constructor if you prefer.

Marc Gravell