【译】All-In-One:加载嵌入资源中的用户控件

原文地址:http://code.msdn.microsoft.com/CSASPNETAccessResourceInAss-6725d61a

你可以在原文中下载源代码,我在文章中不再提供下载链接。

 

介绍

  本项目举例说明了如何通过虚拟路径访问类库中的用户控件和页面,我们继承了VirtualPathProvider和VirtualFile类创建了一个自定义路径提供程序,这个虚拟文件系统能够提供一类像似的文件路径,供不同的程序访问文件或代码。例如,我们可以将相同类型但在不同程序集(a.dll, b.dll)中的文件(a.mp3, b.mp3)使用统一的虚拟路径,像 http://localhost/mp3/a.mp3http://localhost/mp3/b.mp3。通过这种方法,我们的网站变得更加清晰和易于交互。

 

运行示例程序

跟着示例的步骤:

第一步:打开CSASPNETAccessResourceInAssembly.sln,展开CSASPNETAccessResourceInAssembly Web应用程序,按CTRL+ F5浏览Default.aspx。

第二步:我们将会在页面上看到两个用户控件和两个连接,红色边框部分和它下面的连接来自CSASPNETAssembly项目,蓝色边框部分和WebSite/WebPage连接来自本项目。

第三步:你可以点击两个连接来查看两个不同程序集中的页面,Assembly/WebPage 是CSASPNETAssembly项目的页面,Website/WebPage是当前项目的页面。

来自CSASPNETAssembly的页面:

来自本项目的页面:

第四步:完成

 

用到的代码

代码逻辑:

第一步:在Visual Studio 2010 或 Visual Web Developer 2010中创建一个空的Web应用程序,命名为“CSASPNETAccessResourceInAssembly”。这个程序需要新建两个项目:“CSASPNETAccessResourceInAssembly”和“CSASPNETAssembly”。

第二步:在项目CSASPNETAssembly中,创建一个用户控件也Web页面,这个项目是目标项目,另外一个会访问它的资源。为了使页面和用户控件看上去和别的不同,我们需要为他们加入一些文字和特殊颜色的边框。

第三步:像第二步一样为CSASPNETAccessResourceInAssembly添加页面和用户控件,同样需要添加一些文字和边框。然后我们需要添加一个模板页来显示这些资源,新增一个名字为default.aspx的页面,在后台代码中添加加载用户控件和连接。常规的web页面和用户控件,我们可以用相对路径直接访问,但对于程序中的资源,我们需要在url中加入一些特殊的信息。

使用一下代码为default.aspx添加控件和链接:

    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;

        }

    }

 

第四步:万事俱备,现在我们可以创建自定义虚拟文件系统了。首先,创建一个继承自VirtualPathProvider 的类,重写一些必要的方法,例如FileExists、GetFile、GetCacheDependency,这个类用来接收和解析来自web请求,以获得正确的资源。

 

    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);

            }

        }

    }

第五步:然后创建一个虚拟文件类,用来从CustomPathProvider获取路径,并检查url是否合法,并返回相对于程序集的文件流。

    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;

            }

        }

    }

第六步:最后,你需要在Application_Start 事件中注册CustomPathProvider 类,这个提供者会随着程序一起运行。

        protected void Application_Start(object sender, EventArgs e)

        {

            HostingEnvironment.RegisterVirtualPathProvider(new CustomPathProvider());

        }

第七步:编译并调试。

你可能感兴趣的:(one)