views:

417

answers:

2

Hello

I have a custom attribute for my page like this:

[PageDefinition("My page", "~/Parts/MyPage.aspx")]

My PageDefinition looks like this, where AttributeItemDefinitions is get set for Title, Url, IsPage and IsUserControl

public class PageDefinition : AttributeItemDefinitions
{
    public PageDefinition(string title, string url)
        : this()
    {
        Title = title;
        Url = Url;
    }

    public PageDefinition()
    {
        IsPage = true;
        IsUserControl = false;
    }
}

But i can't find any good way to add all page with that attribute to a placeholder where all links should be list with the title and url. Do you have any good idea? Thanks for your help.

+1  A: 

When I've created such custom attributes that define some metadata on a class I've often built a small routine that scans all classes of an assembly using reflection.

In my current project I'm using a IoC framework (other story) and instead of configuring it in a custom config file I've built myself a ComponentAttribute that defines what interface a class belongs to. (From a bird's eye view: I ask the IoC framework for a interface later on and it knows how to instantiate classes that implement that and how they fit together)

To configure that IoC framework I need to call a member of a certain class and tell it which class to interface mappingts exist.

  ioc.ConfigureMapping(classType, interfaceType)

To find all those mappings I use the following two methods in one of my helper classes

 internal static void Configure(IoCContainer ioc, Assembly assembly)
 {
     foreach (var type in assembly.GetTypes())
          AddToIoCIfHasComponentAttribute(type, ioc);
 }

 internal static void AddToIoCIfHasComponentAttribute(Type type, IoC ioc)
 {
     foreach (ComponentAttribute att in type.GetCustomAttributes(typeof(ComponentAttribute), false))
     {
          ioc.ConfigureMapping(attribute.InterfaceType, type);
     }
 }

What I'm doing here is enumerating all of an assemblies' types in the first method, and than evaluting the attribute in the second one.

Back to your problem:

Using a similar approach you could find all the marked classes and record them in a container (ArrayList or similar) along with all the data you have defined in the attribute (Page path, etc.).

Update (Answer to comment)

When you build your program in Visual Studio you normally have one or more projects. For each project you will get a distinct assembly (.dll or .exe file). The code above will examine all the classes within one assembly. Seen that way an assembly is a collection of collected .cs files. So you want to search an assembly, not a directory of .cs files (which are source code and not part of the running application.)

So what's probably is missing: How can you access an assembly from your code when you want to search for classes? You just take ANY class you know (that is in the assembly/project where your other classes are) and obtain the assembly it is in by calling

var assembly = typeof(MyDummyClass).Assembly;

and afterwards you'd call something you derived from the code above

AnalyzeClasses(assembly)

and AnalyzeClasses would look like

 internal static void AnalyzeClasses(Assembly assembly)
 {
     foreach (var type in assembly.GetTypes())
          AnalzyeSingleClass(type);
 }

 internal static void AnalzyeSingleClass(Type type)
 {
     foreach (MyCustomAttribute att in type.GetCustomAttributes(typeof(MyCustomAttribute), false))
     {
          Console.WriteLine("Found MyCustomAttribute with property {0} on class {1}",
                  att.MyCustomAttributeProperty,
                  type);
     }
 }

And you'd just call all that before you run your application code, for example right at the top in main() (for applications) or if it's difficult in advanced you can also call this on demand when you need the collected data. (For example from an ASP.NET page)

froh42
I will look in to this, thanks
Frozzare
Well, i don't figure out a good way to use it. But can't i just search a folder with classes inside? Where the class "myclass.cs" has the attribute?
Frozzare
Frozzare, I've edited my answer as a response to your comment.
froh42
A: 

It might be more than you need but...

I run into this pattern all of the time in my projects so I implemented a type loader that can be supplied with user defined delegates for a type search matching.

http://www.codeproject.com/KB/architecture/RuntimeTypeLoader.aspx

dkackman
Very usefull link, thanks
Frozzare