Go homepage(回首页) Upload pictures (上传图片) Write articles (发文字帖)
The author:(作者)归海一刀published in(发表于) 2014/1/30 0:59:12 Asp.Net中虚拟文件系统的使用_[Asp.Net教程]
在Asp.Net的开发过程中页面文件等都是放在当前网站目录下的,其实我们可以利用.Net2.0新增的虚拟文件系统(VirtualPathProvider)将页面、图片等信息保存到数据库或其他目录中去,达到灵活配置。本文以一个例子来说明虚拟文件系统的使用,要实现的功能场景描述如下:以前开发Asp.Net的web用户控件时,需要把用户控件和当前项目作为同一个项目时才能正常使用,而且发布时需要把dll文件和所有的ascx文件都发布才能使用;另外也不方便作为公用类给其他人使用利用虚拟文件系统后可以把ascx文件作为资源打包到dll中,下次只要有这个dll就可以使用了,不需要ascx文件,很方便。
具体实现步骤如下:一、开发web用户控件这一步和以前的开发没有区别。1、首先新建一个web应用程序(需要VS2005 sp1支持)2、然后在里面开发几个web用户控件3、在ascx文件上右键-〉属性-〉生成操作选择嵌入的资源4、生成dll就可以了(dll的名字为:Test.Control.dll,后面会用到)
二、开发一个虚拟文件系统提供类这一步是最重要的一步。具体思路就是:在系统中注册这个类,然后在每访问一个文件/资源的时候会自动调用这个类,在这个类中判断文件的路径是否是我们定义的,如果是就用我们的逻辑来处理,即从dll中取出资源。首先把类的代码贴出来,我想可能许多人应该和我一样,喜欢直接先看代码:)DllVirtualPathProvider public class DllVirtualPathProvider : System.Web.Hosting.VirtualPathProvider { public DllVirtualPathProvider() { }
public override string CombineVirtualPaths(string basePath, string relativePath) { if (IsAppResourcePath(basePath)) { return null; }
return Previous.CombineVirtualPaths(basePath, relativePath); }
public override System.Runtime.Remoting.ObjRef CreateObjRef(Type requestedType) { return Previous.CreateObjRef(requestedType); }
public override bool DirectoryExists(string virtualDir) { if (IsAppResourcePath(virtualDir)) { return true; } else { return Previous.DirectoryExists(virtualDir); }
}
public override string GetCacheKey(string virtualPath) { if (IsAppResourcePath(virtualPath)) { return null; } else { return Previous.GetCacheKey(virtualPath); } }
public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) { if (IsAppResourcePath(virtualPath)) { return null; } else { return Previous.GetFileHash(virtualPath, virtualPathDependencies); } }
private bool IsAppResourcePath(string virtualPath) { String checkPath = VirtualPathUtility.ToAppRelative(virtualPath); return checkPath.StartsWith("~/MyUserControl/Test.Control.dll/", StringComparison.InvariantCultureIgnoreCase); }
public override bool FileExists(string virtualPath) { return (IsAppResourcePath(virtualPath) || Previous.FileExists(virtualPath)); }
public override VirtualFile GetFile(string virtualPath) { if (IsAppResourcePath(virtualPath)) { return new AssemblyResourceVirtualFile(virtualPath); } else { return Previous.GetFile(virtualPath); } }
public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart) { if (IsAppResourcePath(virtualPath)) { string path = HttpRuntime.AppDomainAppPath + virtualPath.Substring(1);
return new System.Web.Caching.CacheDependency(path); } else { return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart); } } }重点有以下几个:1、必须从VirtualPathProvider类继承2、IsAppResourcePath方法是用来判断是否为我们定义的路径格式:~/MyUserControl/Test.Control.dll/,下面调用的时候就使用这个路径3、注意GetCacheKey方法: public override string GetCacheKey(string virtualPath) { if (IsAppResourcePath(virtualPath)) { return null; } else { return Previous.GetCacheKey(virtualPath); } }这里当符合条件时一定要返回null,如果返回"",会导致所有的用户控件都使用一个key值,从而所有的用户控件都显示同样的内容了。如果返回其他非空字符,会报异常(它会去查找cache,我们是没有的)另外所有的方法当不符合我们的条件时一定要调用 Previous.**** 因为系统中可能有多个虚拟文件提供程序的。
4、GetCacheDependency方法: if (IsAppResourcePath(virtualPath)) { string path = HttpRuntime.AppDomainAppPath + virtualPath.Substring(1);
return new System.Web.Caching.CacheDependency(path); }这个方法是用来决定Cache的使用的,如果返回null,会导致性能严重下降,每次调用用户控件时都会重新编译,这里返回的当前路径(需要在网站目录下再建立子目录:MyUserControl\Test.Control.dll),这个目录下是空的,这样当每次取Cache时都会认为我们的ascx没有修改,不需要重新编译。
5、在GetFile方法中我们返回的是一个AssemblyResourceVirtualFile类: class AssemblyResourceVirtualFile : VirtualFile { string path; public AssemblyResourceVirtualFile(string virtualPath) : base(virtualPath) { path = VirtualPathUtility.ToAppRelative(virtualPath); }
public override System.IO.Stream Open() { string[] parts = path.Split('/'); string assemblyName = parts[2]; string resourceName = parts[3]; assemblyName = Path.Combine(HttpRuntime.BinDirectory, assemblyName); System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(assemblyName); if (assembly != null) { return assembly.GetManifestResourceStream(resourceName); } return null; } }这个类的目的就是从我们的dll中读出资源文件。
三、注册这个虚拟文件提供程序这一个很简单,在global.asax中注册: protected void Application_Start(object sender, EventArgs e) { System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new DllVirtualPathProvider()); }四、调用dll中的用户控件 Control control1 = this.LoadControl("/MyUserControl/Test.Control.dll/Test.Control.Sample.List.ascx"); Control control2 = this.LoadControl("/MyUserControl/Test.Control.dll/Test.Control.Sample.Sample.ascx");
form1.Controls.Add(control1); form1.Controls.Add(control2);比较简单,就是路径要和前面的一致。
来源:http://www.cnblogs.com/firstyi
赞