Могу ли я загрузить ITemplate из базы данных или строки? - PullRequest
0 голосов
/ 22 марта 2011

Я хочу реализовать некоторые шаблоны в веб-приложении и хотел использовать шаблонные элементы управления ASP.NET. Однако я не хочу полагаться на физические файлы .ascx или VirtualPathProvider для загрузки шаблонов.

Я хочу иметь возможность загружать шаблоны из базы данных или другого хранилища данных (в памяти?). Существует ли какая-либо реализация метода LoadTemplate (), которая возвращает ITemplate с учетом строкового представления шаблона .ascx?

Если нет, то как мне написать один?

К вашему сведению, Kentico имеет аналогичную функцию, но они используют VirtualPathProvider для использования LoadTemplate() в классе TemplateControl. С помощью этого метода они могут загружать шаблоны (они называют их преобразованиями), хранящиеся в базе данных.

Ответы [ 2 ]

1 голос
/ 07 октября 2011

Я столкнулся с подобной проблемой. Тем не менее, 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) Используйте несколько хакерский обходной путь:

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

1 голос
/ 30 августа 2011

Да, VirtualPathProvider - это, вероятно, метод, который вы захотите использовать, если строка или база данных является источником, который вы хотите использовать.(Существуют также генераторы кода, которые могут генерировать код, но обычно они используются при динамическом построении кода, а не при загрузке из внешнего источника, как в вашем случае.)

Вы не упоминаете почему вы не хотите использовать VirtualPathProvider, хотя.Это происходит из-за того, что вы не хотите или не можете из-за каких-то особых требований, которые у вас есть в конкретной ситуации?

Наконец, если «кажется тривиальным» загружать и компилировать код динамически, то вы незнать, что должна делать вся система .Net, прежде чем она сможет запускать динамический код - генерацию сборки, компиляцию и JIT, контексты приложения, разрешение имен классов / элементов, безопасность кода и т. д. Возможно, вы только что были избалованы тем, насколько легко.Net сделал делать другие сложные задачи.; -)

...