ASP.NET 2.0 里的VirtualPathProvider

ASP.NET 2.0  快速入门教程里很简要地提到了VirtualPathProvider,听上去很powerful,查看了一下文档,大概是说,

“。。。。
The VirtualPathProvider类提供了一套方法以在一个Web 应用里实现虚拟文件系统。在虚拟文件系统里,文件和文件夹是由一个 data store 来管理的,而不是由通常的服务器操作系统的文件系统所管理。譬如,你可以使用虚拟文件系统来在 SQL Server 数据库里存储内容。

在这个虚拟文件系统里,你可以存储下面这些文件
1。ASP.NET 页面, master页面,用户控件以及其他对象
2。以.htm 和.jpg为扩展名的.标准的网页
3。映射到BuildProvider实例的任何自定义扩展文件
4。存在App_Theme文件夹的任何赋名的 theme

但不能存储那些产生application-level assemblies的文件和文件夹,譬如不能存储
1。Global.asax
2。Web.config
3。应用级的文件夹,Bin,App_Code, App_GlobalResources,以及App_LocalResources
4。应用的数据文件夹,App_Data.

。。。”

文档提供了一个例子,通过一个 DataSet 对象里的信息实现一个虚拟文件系统。

看完后并没有留下很深的印象,直到看到了Scott Guthrie的演示里的例子,由一个Access文件提供的文件系统时,真的感觉这东西真的很酷,感兴趣者可以去Scott Guthrie的网站下载对应的PPT和编码例子。

ASP.NET 2.0 Tips/Tricks Slides + Demos

下面是我依样画葫芦写的一个简单的Provider例子,主要是用来验证可以使用codefile。想要试着运行的话,生成一个虚拟目录,然后建立一个App_Code文件夹,把下面内容存成一个.cs文件,然后在浏览器里访问

http://localhost/你的应用名字/abc/def.aspx

应用名字后面的文件夹子,文件名是任意的,只要是以.aspx结尾

===============================

using System;
using System.IO;
using System.Text;
using System.Web.Caching;
using System.Web.Hosting;
using System.Collections;

namespace JoyCode
{

    class SimpleVirtualFile : VirtualFile
    {

        string path;
        public SimpleVirtualFile(string virtualPath) : base(virtualPath)
        {
            path = virtualPath.ToLower();
        }

        public override bool IsDirectory
        {
            get
            {
                if(path.EndsWith(“.aspx”) || path.EndsWith(“.cs”))
                    return false;
                return true;
            }
        }

        public override Stream Open()
        {
           string Html = @”<%@ Page Language=””C#”” CodeFile=””Test.aspx.cs”” Inherits=””ASPNET20.Test_aspx””%>
hello world: <%=DateTime.Now%><BR>”;

            string Code = @”using System;
using System.Web.UI;

namespace ASPNET20
{
  public partial class Test_aspx : Page
  {
 void Page_Load(Object sender, EventArgs e)
        {
            Response.Write(“”hello world from Test_aspx.Page_Load:”” + DateTime.Now + “”<BR>””);
        }
  }
}
        “;

            Stream stream = null;
            if (!IsDirectory)
            {
                if (path.EndsWith(“.aspx”))
                    stream = new MemoryStream(Encoding.ASCII.GetBytes(Html));
                else if (path.EndsWith(“.cs”))
                    stream = new MemoryStream(Encoding.ASCII.GetBytes(Code));
            }

            if (stream != null)
                stream.Seek(0, SeekOrigin.Begin);

            return stream;
        }
    }

    public class SimpleVirtualPathProvider : VirtualPathProvider
    {

        public static void AppInitialize()
        {
            SimpleVirtualPathProvider provider = new SimpleVirtualPathProvider();
            HostingEnvironment.RegisterVirtualPathProvider(provider);
        }

        public override bool FileExists(string virtualPath)
        {
            virtualPath = virtualPath.ToLower();

            if (virtualPath.EndsWith(“.aspx”) || virtualPath.EndsWith(“.cs”))
                return true;
            else
                return false;
        }

        public override bool DirectoryExists(string virtualDir)
        {
            return !FileExists(virtualDir);
        }

        public override VirtualFile GetFile(string virtualPath)
        {
            return new SimpleVirtualFile(virtualPath);
        }

        //this prevents an error if you have a path with folder names
        //参考Valvert 在下面这个帖子里的答复
        //http://forums.asp.net/921762/ShowPost.aspx
        public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
        {
            return null;
        }
    }
}