ASP.NET读取DLL文件中的页面和用户控件(VirtualPathProvider VirtualFile)

这篇文章用来介绍一下如何通过VirtualPathProvider来获取程序集中的页面和用户控件的内容。这样做的好处是可以在项目中达到所有的文件路径是统一的,不管你的页面或者控件来自于任何一个程序集。

举个例子,你的项目中所有的aspx页面均存放在Website这个目录下,那么通常你可以使用相对路径~/WebSite/WebPage.aspx来找到目录下的WebPage页面。

当你需要从某个程序集(DLL)中加载一个page到你的页面上来。通常情况下必须要使用Assembly.load()方法来找到它,并且很有可能需要使用到反射来确定它的类型,并且将他返回给页面,但是当你使用VirtualFile和VirtualPathProvider的时候,这时候对于父页面来说,它只需要去读取这个custom file的虚拟路径即可,具体返回的stream由你自己来定义(例如你仍然可以使用Assembly.load来获取文件)。那么你可以自定义它的路径来保证路径的一致性。

举个例子来看看如何来实现这个功能,能够更清晰一些。

准备工作是建一个Web应用程序,创建一个页面WebPage和一个用户控件WebUserControl,同理新建一个另外一个项目也包含同名的这两个文件,当然你最好在页面上区分它们来自本项目还是其他项目。例如本项目的写“I am from 本项目名”,其他项目则改为其他项目的名字。

[本示例完整源码下载(0分)] http://download.csdn.net/detail/aa466564931/4414671

首先我们创建一个CustomFile继承自VirtualFile,这个类的作用是加载来自其他程序集的文件并且返回给VirtualFileProvider使用:

    public class CustomFile: VirtualFile
    {
        string path
        {
            get;
            set;
        }

        public CustomFile(string virtualPath)
            : base(virtualPath)
        {
            path = VirtualPathUtility.ToAppRelative(virtualPath);
        }

        /// <summary>
        /// Override Open method to load resource files of assembly.
        /// </summary>
        /// <returns></returns>
        public override System.IO.Stream Open()
        {
            string[] strs = path.Split('/');
            string name = strs[2];
            string resourceName = strs[3];
            name = Path.Combine(HttpRuntime.BinDirectory, name);
            Assembly assembly = Assembly.LoadFile(name);
            if (assembly != null)
            {
                Stream s = assembly.GetManifestResourceStream(resourceName);
                return s;
            }
            else
            {
                return null;
            }
        }
    }


接着创建一个CustomVirtualProvider类继承自VirtualPathProvider,这里我们必须实现以下几个方法(Assembly是我自定义的文件名,你以为改为任意名称),注意AssemblyPathExist这个方法,在使用base.FileExists判断之前先进行我们的自定义路径的判断,如果存在则使用VirtualFile来取代默认的方法:

    public class CustomPathProvider : VirtualPathProvider
    {
        public CustomPathProvider()
        { 
        }

        /// <summary>
        /// Make a judgment that application find path contains specifical folder name.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private bool AssemblyPathExist(string path)
        {
            string relateivePath = VirtualPathUtility.ToAppRelative(path);
            return relateivePath.StartsWith("~/Assembly/", StringComparison.InvariantCultureIgnoreCase);
        }

        /// <summary>
        /// If we can find this virtual path, return true.
        /// </summary>
        /// <param name="virtualPath"></param>
        /// <returns></returns>
        public override bool FileExists(string virtualPath)
        {
            if (this.AssemblyPathExist(virtualPath))
            {
                return true;
            }
            else 
            {
                return base.FileExists(virtualPath);
            }
        }

        /// <summary>
        /// Use custom VirtualFile class to load assembly resources.
        /// </summary>
        /// <param name="virtualPath"></param>
        /// <returns></returns>
        public override VirtualFile GetFile(string virtualPath)
        {
            if (AssemblyPathExist(virtualPath))
            {
                return new CustomFile(virtualPath);
            }
            else
            {
                return base.GetFile(virtualPath);
            }
        }

        /// <summary>
        /// Return null when application use virtual file path.
        /// </summary>
        /// <param name="virtualPath"></param>
        /// <param name="virtualPathDependencies"></param>
        /// <param name="utcStart"></param>
        /// <returns></returns>
        public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
        {
            if (AssemblyPathExist(virtualPath))
            {
                return null;
            }
            else
            {
                return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
            }
        }
    }

OK,接下来我们就可以使用我们自定义的path来加载程序集中的文件了,我们把一下代码放在default页面中:

注意~/WebSite/WebUserControl.ascx是本项目的文件,~/Assembly/CSASPNETAssembly.dll/CSASPNETAssembly.WebUserControl.ascx是来自于CSASPNETAssembly.dll的文件:

    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Add relative web pages and user controls in assembly and this application.
            DataTable tab = this.InitializeDataTable();
            if (tab != null && tab.Rows.Count != 0)
            {
                for (int i = 0; i < tab.Rows.Count; i++)
                {
                    Control control = Page.LoadControl(tab.Rows[i]["UserControlUrl"].ToString());
                    UserControl usercontrol = control as UserControl;
                    Page.Controls.Add(usercontrol);
                    HyperLink link = new HyperLink();
                    link.NavigateUrl = tab.Rows[i]["WebPageUrl"].ToString();
                    link.Text = tab.Rows[i]["WebPageText"].ToString();
                    Page.Controls.Add(link);
                }
            }
        }

        /// <summary>
        /// Initialize a DataTable variable for storing URL and text properties. 
        /// </summary>
        /// <returns></returns>
        protected DataTable InitializeDataTable()
        {
            DataTable tab = new DataTable();
            DataColumn userControlUrl = new DataColumn("UserControlUrl",Type.GetType("System.String"));
            tab.Columns.Add(userControlUrl);
            DataColumn webPageUrl = new DataColumn("WebPageUrl", Type.GetType("System.String"));
            tab.Columns.Add(webPageUrl);
            DataColumn webPageText = new DataColumn("WebPageText", Type.GetType("System.String"));
            tab.Columns.Add(webPageText);
            DataRow dr = tab.NewRow();
            dr["UserControlUrl"] = "~/Assembly/CSASPNETAssembly.dll/CSASPNETAssembly.WebUserControl.ascx";
            dr["WebPageUrl"] = "~/Assembly/CSASPNETAssembly.dll/CSASPNETAssembly.WebPage.aspx";
            dr["WebPageText"] = "Assembly/WebPage";
            DataRow drWebSite = tab.NewRow();
            drWebSite["UserControlUrl"] = "~/WebSite/WebUserControl.ascx";
            drWebSite["WebPageUrl"] = "~/WebSite/WebPage.aspx";
            drWebSite["WebPageText"] = "WebSite/WebPage";
            tab.Rows.Add(dr);
            tab.Rows.Add(drWebSite);
            return tab;
        }
    }


好了接下来你可以debug看下结果了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值