通过VirtualPathProvider使用嵌入资源

VirtualPathProvider类,提供了一组方法,使 Web 应用程序可以从虚拟文件系统中检索资源。

参见MSDN:http://msdn.microsoft.com/zh-cn/library/system.web.hosting.virtualpathprovider.aspx

 

遇到这样一个需求,要将.ascx作为嵌入资源放到一个Library项目中,在Web App中需要可以使用。

 

上网查找后发现,VirtualPathProvider类可以实现这个目的。

 

步骤一:

通过继承VirtualPathProvider类,实现自己的AssemblyResourceVirtualPathProvider,用来为Assembly中的Resource提供支持。

 

VirtualPathProvider代码

    
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。

 

VirtualFile代码
    public class AssemblyResourceVirtualFile : VirtualFile
    {
        
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。

 

Global代码

        
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。

 

Page代码
        protected override void OnInit(EventArgs e)
        {
            
//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提供访问支持。

 

JS嵌入资源
            //获取对程序集内资源的 URL 引用 的 虚拟路径方法
            
//当然,可以在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);
            }

 

 

 代码示例:https://files.cnblogs.com/xujiaoxiang/WebDemo.zip

posted @ 2010-05-24 17:45  翱翔  阅读(4174)  评论(3编辑  收藏  举报