views:

57

answers:

1

Hello All,

I have created a custom Attribute to decorate a number of classes that I want to query for at runtime:

[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class ExampleAttribute : Attribute
{
    public ExampleAttribute(string name)
    {
        this.Name = name;
    }

    public string Name
    {
        get;
        private set;
    }
}

Each of these classes derive from an abstract base class:

[Example("BaseExample")]
public abstract class ExampleContentControl : UserControl
{
    // class contents here
}

public class DerivedControl : ExampleContentControl
{
    // class contents here
}

Do I need to put this attribute on each derived class, even if I add it to the base class? The attribute is marked as inheritable, but when I do the query, I only see the base class and not the derived classes.

From another thread:

var typesWithMyAttribute = 
    from a in AppDomain.CurrentDomain.GetAssemblies()
    from t in a.GetTypes()
    let attributes = t.GetCustomAttributes(typeof(ExampleAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = t, Attributes = attributes.Cast<ExampleAttribute>() };

Thanks, wTs

+1  A: 

I ran your code as is, and got the following result:

{ Type = ConsoleApplication2.ExampleContentControl, Attributes = ConsoleApplication2.ExampleAttribute[] }
{ Type = ConsoleApplication2.DerivedControl, Attributes = ConsoleApplication2.ExampleAttribute[] }

So it seems to work... You sure something else isn't going on?

Nader Shirazie
Try putting a derived class into another project, referencing the first. If I put the derived class in the same namespace as the base, it does work.
Wonko the Sane
Well, half figured it out - the other assemblies weren't loaded yet when the LINQ query was called. I guess the question then becomes, "how do I get all the assemblies that are associated with my executable (i.e. what do I replace the AppDomain.CurrentDomain.GetAssemblies() call with)?"
Wonko the Sane
Right, that makes sense... you need to find some way to force a load on all assemblies that may matter. This really depends on how your app is structured. If, for example, all your assemblies are loaded from the folder where the app runs, you could scan through and force a load. If you're doing anything exotic, like redirecting assembly loads... its trickier. If you know ahead of time which assemblies you expect to be there, then the simplest thing is just to reference some type within each of those assemblies.
Nader Shirazie
Yeah, that's true. I guess I was hoping to avoid the "preloading" thing, but perhaps there isn't a nice, clean way of doing this.
Wonko the Sane
Well, if you're going to scan through loaded assemblies, then that's the choice you have. If all you want to do is scan the assemblies without actually loading it into the appdomain, you can do that too...
Nader Shirazie
Marked as answer for answer + comments that pointed me in the right direction. Thanks!
Wonko the Sane