VirtualPathProvider类,提供了一组方法,使 Web 应用程序可以从虚拟文件系统中检索资源。
参见MSDN:http://msdn.microsoft.com/zh-cn/library/system.web.hosting.virtualpathprovider.aspx
遇到这样一个需求,要将.ascx作为嵌入资源放到一个Library项目中,在Web App中需要可以使用。
上网查找后发现,VirtualPathProvider类可以实现这个目的。
步骤一:
通过继承VirtualPathProvider类,实现自己的AssemblyResourceVirtualPathProvider,用来为Assembly中的Resource提供支持。
public class AssemblyResourceVirtualPathProvider : System.Web.Hosting.VirtualPathProvider
{
/// <summary>
/// AssemblyPath与VirtualPath映射
/// </summary>
private string _VirtualPath;
private string _AssemblyPath;
private string VirtualPath { get { return _VirtualPath; } }
private string AssemblyPath { get { return _AssemblyPath; } }
public AssemblyResourceVirtualPathProvider( string virtualPath, string assemblyPath)
{
_VirtualPath = " ~/ " + virtualPath;
_AssemblyPath = assemblyPath;
}
/// <summary>
/// 是否是AssemblyResource类型的VirtualPath
/// </summary>
/// <param name="virtualPath"> virtualPath </param>
/// <returns></returns>
private bool IsAssemblyResourceVirtualPath( string virtualPath)
{
string path = VirtualPathUtility.ToAppRelative(virtualPath);
return path.StartsWith(VirtualPath, StringComparison.InvariantCultureIgnoreCase);
}
/// <summary>
/// 获取virtualPath对应Assembly内的ResourceName
/// </summary>
/// <param name="virtualPath"> virtualPath </param>
/// <returns></returns>
private string GetResourceName( string virtualPath)
{
return VirtualPathUtility.GetFileName(virtualPath);
}
#region override
/// <summary>
/// 获取VirtualFile
/// </summary>
/// <param name="virtualPath"></param>
/// <returns></returns>
public override VirtualFile GetFile( string virtualPath)
{
if (IsAssemblyResourceVirtualPath(virtualPath))
{
string resourceName = this .GetResourceName(virtualPath);
return new AssemblyResourceVirtualFile(virtualPath, AssemblyPath, resourceName);
}
else
{
return Previous.GetFile(virtualPath);
}
}
/// <summary>
/// virtualPath指定的文件是否存在。
/// </summary>
/// <param name="virtualPath"></param>
/// <returns></returns>
public override bool FileExists( string virtualPath)
{
if (IsAssemblyResourceVirtualPath(virtualPath))
{
// return true;
Assembly assembly = Assembly.LoadFrom(AssemblyPath);
if (assembly != null )
{
string resourceName = this .GetResourceName(virtualPath);
return (assembly.GetManifestResourceInfo(resourceName) != null );
}
return false ;
}
else
{
return Previous.FileExists(virtualPath);
}
}
public override bool DirectoryExists( string virtualDir)
{
if (IsAssemblyResourceVirtualPath(virtualDir))
{
return true ;
}
else
{
return Previous.DirectoryExists(virtualDir);
}
}
public override string GetFileHash( string virtualPath, IEnumerable virtualPathDependencies)
{
return null ;
// HashCodeCombiner combiner = new HashCodeCombiner();
// foreach (string str in virtualPathDependencies)
// {
// string fileName = HostingEnvironment.MapPathInternal(str);
// combiner.AddFile(fileName);
// }
// return combiner.CombinedHashString;
}
public override CacheDependency GetCacheDependency( string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
{
return null ;
// System.Collections.Specialized.StringCollection fullPathDependencies = null;
/// / Get the full path to all dependencies.
// foreach (string virtualDependency in virtualPathDependencies)
// {
// if (fullPathDependencies == null)
// fullPathDependencies = new System.Collections.Specialized.StringCollection();
// fullPathDependencies.Add(virtualDependency);
// }
// if (fullPathDependencies == null)
// return null;
/// / Copy the list of full-path dependencies into an array.
// string[] fullPathDependenciesArray = new string[fullPathDependencies.Count];
// fullPathDependencies.CopyTo(fullPathDependenciesArray, 0);
/// / Copy the virtual path into an array.
// string[] virtualPathArray = new string[1];
// virtualPathArray[0] = virtualPath;
// return new CacheDependency(virtualPathArray, fullPathDependenciesArray, utcStart);
}
// public override string CombineVirtualPaths(string basePath, string relativePath)
// {
// if (IsAssemblyResourceVirtualPath(basePath))
// {
// return null;
// }
// else
// {
// return Previous.CombineVirtualPaths(basePath, relativePath);
// }
// }
// public override System.Runtime.Remoting.ObjRef CreateObjRef(Type requestedType)
// {
// return Previous.CreateObjRef(requestedType);
// }
// public override string GetCacheKey(string virtualPath)
// {
// if (IsAssemblyResourceVirtualPath(virtualPath))
// {
// return null;
// }
// else
// {
// return Previous.GetCacheKey(virtualPath);
// }
// }
#endregion
}
步骤二:
通过继承VirtualFile类,实现AssemblyResourceVirtualPathProvider的AssemblyResourceVirtualFile,用来提供Resource的Open。
{
private string AssemblyPath;
private string ResourceName;
public AssemblyResourceVirtualFile( string virtualPath, string assemblyPath, string resourceName)
: base (virtualPath)
{
AssemblyPath = assemblyPath; // Path.Combine(HttpRuntime.BinDirectory, assemblyPath);
ResourceName = resourceName;
}
public override System.IO.Stream Open()
{
Assembly assembly = Assembly.LoadFrom(AssemblyPath);
if (assembly != null )
{
return assembly.GetManifestResourceStream(ResourceName);
}
return null ;
}
}
步骤三:
在Global.asax中注册VirtualPathProvider。
protected void Application_Start( object sender, EventArgs e)
{
string assemblyPath = " WebControlLibrary.dll " ;
assemblyPath = Path.Combine(HttpRuntime.BinDirectory, assemblyPath);
AssemblyResourceVirtualPathProvider provider = new AssemblyResourceVirtualPathProvider( " WebControlDemo " , assemblyPath);
// 按链表方式链接注册的VirtualPathProvider。
HostingEnvironment.RegisterVirtualPathProvider(provider);
}
步骤四:
创建Library项目,添加Web User Control,将.ascx文件为嵌入资源。
步骤五:
在Web App的页面中使用Web User Control。
{
// LoadControl中获取对程序集内资源
// 当然,可以在aspx中使用:
// <%@ Register Src="WebControlDemo/WebControlLibrary.WebUserControl.ascx" TagName="WebUserControl" TagPrefix="uc1" %>
// <uc1:WebUserControl id="WebUserControl1_1" runat="server"/>
WebUserControl1 = this .LoadControl( " WebControlDemo/WebControlLibrary.WebUserControl.ascx " ) as WebUserControl;
SubWebUserControl1 = this .LoadControl( " WebControlDemo/WebControlLibrary.SubDirectory.SubWebUserControl.ascx " ) as SubWebUserControl;
this .form1.Controls.Add(WebUserControl1);
this .form1.Controls.Add(SubWebUserControl1);
base .OnInit(e);
}
结束语:
通过嵌入资源的联想,可以将JS文件作为嵌入资源,同样可以通过VirtualPathProvider提供访问支持。
// 当然,可以在aspx中使用:<script language="javascript" src="WebControlDemo/WebControlLibrary.VirtualPathProvider.js"></script>
if ( ! this .ClientScript.IsClientScriptIncludeRegistered(GetType(), " JS By VirtualPathProvider " ))
{
string webUrl = " WebControlDemo/WebControlLibrary.VirtualPathProvider.js " ;
this .ClientScript.RegisterClientScriptInclude(GetType(), " JS By VirtualPathProvider " , webUrl);
}
// 获取对程序集内资源的 URL 引用 的 一般方法
if ( ! this .ClientScript.IsClientScriptIncludeRegistered(GetType(), " JS By WebResourceUrl " ))
{
string webUrl = Page.ClientScript.GetWebResourceUrl( new WebUserControl().GetType(), " WebControlLibrary.WebResourceUrl.js " );
this .ClientScript.RegisterClientScriptInclude(GetType(), " JS By WebResourceUrl " , webUrl);
}