Выполнение динамического кода Razor - как? - PullRequest
1 голос
/ 01 июня 2011

В этот пост Я задумался о чистом коде при интернационализации приложения. это приводит к этому второму запросу ... предположим, что я хотел вызвать функцию, подобную этой:

@Html.RenderWithTags("Help",
    new Dictionary<string, string>() { "HelpPage", "@Html.ActionLink(...)" }
)

такой, что я ищу строку в моем локальном файле ресурсов, содержащую встроенные «теги», например, Название ресурса «Помощь» содержит:

Мы предлагаем вам прочитать нашу [HelpPage] прежде чем продолжить

, а затем мой метод .RenderWithTags () будет расширять теги, но динамически выполнять код в переданном словаре, например замените [HelpPage] на то, что @Html.ActionLink(...) производит.

Я знаю, что могу использовать Microsoft.CSharp.CSharpCodeProvider().CreateCompiler() для компиляции кода C # на лету, но как насчет кода Razor?

Ответы [ 2 ]

3 голосов
/ 01 июня 2011

Это будет довольно сложно сделать.

Вместо этого вы должны поместить делегатов в свой словарь.
Например:

new Dictionary<string, Func<string>>() { 
    { "HelpPage", () => Html.ActionLink(...).ToString() }
}

Если вы создаете словарь на странице Razor, вы также можете использовать встроенные помощники :

new Dictionary<string, Func<Something, HelperResult>>() { 
    { "HelpPage", @Html.ActionLink(...) }
}

Это позволит использовать произвольную разметку Razor в значениях.

Однако я, вероятно, рекомендую вам создать один глобальный словарь в коде, чтобы вам не нужно было повторять определения на разных страницах. (В зависимости от того, как вы его используете)

0 голосов
/ 03 июня 2011

в итоге решение получилось довольно гладким.Без SLaks это было бы невозможно, я очень благодарен за помощь (хотя я не использовал встроенных помощников (но спасибо за вступление (они очень крутые))).Теперь моя страница содержит это:

@{
    Dictionary<string, MvcHtmlString> tokenMap = new Dictionary<string, MvcHtmlString>() {
        {"HelpPage", Html.ActionLink("help page", "Help", "Home") }
    };
}

и где-то ниже у меня есть:

@this.Resource("Epilogue", tokenMap)

Для достижения этой простоты:

public static class PageExtensions
{
    public static MvcHtmlString Resource(this WebViewPage page, string key)
    {
        HttpContextBase http = page.ViewContext.HttpContext;
        string ret = (string) http.GetLocalResourceObject(page.VirtualPath, key);
        return MvcHtmlString.Create(ret);
    }

    public static MvcHtmlString Resource(
        this WebViewPage page, string key, 
        Dictionary<string, MvcHtmlString> tokenMap
    ) {
        HttpContextBase http = page.ViewContext.HttpContext;
        string text = (string) http.GetLocalResourceObject(page.VirtualPath, key);
        return new TagReplacer(text, tokenMap).ToMvcHtmlString();
    }
}

... и:

public class TagReplacer
{
    Dictionary<string, MvcHtmlString> tokenmap;
    public string Value { get; set; } 

    public TagReplacer(string text, Dictionary<string, MvcHtmlString> tokenMap)
    {
        tokenmap = tokenMap;

        Regex re = new Regex(@"\[.*?\]", RegexOptions.IgnoreCase);
        Value = re.Replace(text, new MatchEvaluator(this.Replacer));
    }

    public string Replacer(Match m)
    {
        return tokenmap[m.Value.RemoveSet("[]")].ToString();
    }

    public MvcHtmlString ToMvcHtmlString()
    {
        return MvcHtmlString.Create(Value);
    }
}

... с небольшой дополнительной помощью:

public static class ObjectExtensions
{
    public static string ReplaceSet(this string text, string set, string x)
    {
        for (int i = 0; i < set.Length; i++)
        {
            text = text.Replace(set[i].ToString(), x);
        }
        return text;
    }
    public static string RemoveSet(this string text, string set)
    {
        return text.ReplaceSet(set, "");
    }
}

комментарии или отзывы о том, как это могло бы быть лучше, приветствуется!

...