Vault of Thoughts

2006-05-31

Please visit my new blog at vaultofthoughts.net

PathsBuildProvider

Some time ago I have found some articles about a feature of ASP.NET called the Build Providers. I especially liked the one about generating classes representing tables from the database. More on that one on Fritz Onion's blog.
Since then I have found numerous ways of using build providers to make my life easier. Today I have built a library that will greatly simplify keeping all Response.Redirect's up to date.



So without further ado I present the PathsBuildProvider.
Using it is as simple as placing a single file with ".pbp" extenstion in the "App_Code" directory and adding a build provider under the compilation section of of the "web.config" file and:


type="PathsBuildProvider.PathsBuildProvider" extension=".pbp"

The .pbp file should contain one word which will be used as a namespace for the generated types. If the file is empty this namespace will default to "Paths".
From now on you can type your namespace name and when you hit "." the name of the application should appear as the only choice. The instance of this class provides a way to access the names of all files located in the application folder in a strongly typed way i.e.: each file is represented by a property such as "Default_aspx". Such a property returns an absolute virtual path to a file so that it can be used in places sucha as Response.Redirect, or Server.MapPath.
Directories are also accessible by means of the properties prefixed with "_". Each directory provides access to its files and sub directories.


You can see an example of how it looks here:



I have put the code for the soulution outside the blog or at the alternative location.


Keep in mind that the code is for demonstrational purposes only and as so it is not a production quality :-). Feel free to use it as you wish though. Any feedback is always welcome.


kick it on dotnetkicks.com


Liked this article? digg it

If you liked this article why not support its author by making a donation?

4 Comments:

  • I made a slight change to your code. In the ClassGenerator.CreateProperty method, I did as follows:

    private CodeMemberProperty CreateProperty(string name, CodeTypeReference type, CodeMethodReturnStatement returnStatement)
    {
    CodeMemberProperty property = new CodeMemberProperty();
    property.Name = name;
    property.Type = type;
    property.Attributes = MemberAttributes.Public | MemberAttributes.Static;
    property.GetStatements.Add(returnStatement);
    return property;
    }

    Essentially, I just changed it so that the properties are static. It makes them a bit easier to work with.

    By Anonymous Anonymous, at 8:04 PM  

  • Actually this is what I first implemented. It has however one major drawback. You cannot do something like:
    Approot.Directory1.Directory2.Page_aspx.
    This is because when you get to the point of Approot.Directory1 what you expect the property Directiry1 return something which in turn has a property Directory2. With static properties what can you return?

    By Blogger Mikeon, at 8:17 PM  

  • Whoops. Guess I should have thought of that. Here's the fix.

    private CodeMemberProperty CreateDirectoryProperty(string name, CodeTypeReference type, CodeMethodReturnStatement returnStatement)
    {
    CodeMemberProperty property = new CodeMemberProperty();
    property.Name = name;
    property.Type = type;
    property.Attributes = MemberAttributes.Public;
    property.GetStatements.Add(returnStatement);
    return property;
    }

    //Then, in the ProcessSubDirectories, I change it like so

    private void ProcessSubDirectories(string directoryName, CodeTypeDeclaration type)
    {
    string[] directories = Directory.GetDirectories(directoryName);
    foreach (string directory in directories)
    {
    CodeGenerator cg = new CodeGenerator(appPath);
    CodeTypeDeclaration innerType = cg.GetTypeDeclaration(directory);
    type.Members.Add(innerType);
    string propertyName = "_" + innerType.Name;
    CodeMemberProperty property = CreateDirectoryProperty(propertyName, new CodeTypeReference(innerType.Name),
    new CodeMethodReturnStatement(
    new CodeObjectCreateExpression(
    new CodeTypeReference(innerType.Name))));
    type.Members.Add(property);
    }
    }


    This should allow static accessors for the files, while allowing directories to work properly.

    Cool code, by the way.

    By Anonymous Anonymous, at 8:23 PM  

  • This comment has been removed by a blog administrator.

    By Blogger Mikeon, at 8:38 PM  

Post a Comment

<< Home