0

我希望在 Web 应用程序中实现一些模板,并希望利用 ASP.NET 的模板化控件。但是,我不想依赖物理 .ascx 文件或 VirtualPathProvider 来加载模板。

我希望能够从数据库或其他数据存储(在内存中?)加载模板。 是否有任何 LoadTemplate() 方法的实现,它返回一个给定 .ascx 模板的字符串表示形式的 ITemplate?

如果没有,我将如何写一个?

仅供参考,Kentico 具有类似的功能,但它们依赖于在类上VirtualPathProvider才能使用。使用该方法,他们能够加载存储在数据库中的模板(他们称之为转换)。LoadTemplate()TemplateControl

4

2 回答 2

1

VirtualPathProvider的,如果字符串或数据库是您要使用的源,则可能是您要使用的方法。(也有可以发出代码的代码生成器,但通常在动态构建代码时使用这些生成器 - 不像您的情况那样从外部源加载。)

不过,您没有提到为什么不想使用 VirtualPathProvider 。是因为不想,还是因为您在特定情况下有一些特殊要求而不能?

最后,如果动态加载和编译代码“看起来很简单”,那么你不知道整个 .Net 系统在运行动态代码之前必须做什么——程序集生成、编译和 JIT、应用程序上下文、类/member 名称解析、代码安全等。也许您刚刚被 .Net 使执行其他复杂任务变得多么容易被宠坏了。;-)

于 2011-08-30T18:18:08.043 回答
1

我一直面临着类似的问题。但是,VirtualPathProvider 实现如此小的收益实在是太麻烦了——更不用说它在安全方面的实现似乎有点风险。我发现了两种可能的解决方法:

1)使用反射来得到你想要的:

var page = HttpContext.Current.Handler as Page;
string text = "<table><tr><td>Testing!!!</td></tr></table>";
var systemWebAssembly = System.Reflection.Assembly.GetAssembly(typeof(Page));
var virtualPathType = systemWebAssembly.GetTypes().Where(t => t.Name == "VirtualPath").FirstOrDefault(); // Type.GetType("System.Web.VirtualPath");
var createMethod = virtualPathType.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public).Where(m => m.Name == "Create" && m.GetParameters().Length == 1).FirstOrDefault();
object virtualPath = createMethod.Invoke(null, new object[]
{ 
    page.AppRelativeVirtualPath 
});
var template = (ITemplate)typeof(TemplateParser).GetMethod("ParseTemplate", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).Invoke(null, new object[]{text, virtualPath, true});

2)使用一个有点hacky的解决方法:

var page = HttpContext.Current.Handler as Page;
string text = "<table><tr><td>Testing!!!</td></tr></table>";
string modifiedText = string.Format("<asp:UpdatePanel runat=\"server\"><ContentTemplate>{0}</ContentTemplate></asp:UpdatePanel>", text);
var control = page.ParseControl(modifiedText);
var updatePanel = control.Controls[0] as UpdatePanel;
var template = updatePanel.ContentTemplate;

我公开地认为两者都不是一个很好的解决方案。理想情况下,.Net Framework 中会有一种方法来处理这类事情。就像是:

public class TemplateParser
{
    public static ITemplate ParseTemplate(string content, string virtualPath, bool ignoreParserFilter)
    {
        return TemplateParser.ParseTemplate(string content, VirtualPath.Create(virtualPath), ignoreParserFilter);
    }
}

这将减轻实现 VirtualPathProvider 的整体需求。也许我们会在 ASP.NET vNext 中看到它 :-)

于 2011-10-07T13:25:30.780 回答