动态Razor代码执行 - 如何?

时间:2011-06-01 18:56:42

标签: c# asp.net-mvc-3 dynamic razor execution

this post中,我想知道应用程序国际化时的清洁代码。导致第二个查询...假设我想调用这样的函数:

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

这样我在我的本地资源文件中查找包含嵌入式“标签”的字符串,例如资源名称“帮助”包含:

  

我们建议您阅读我们的[帮助页面]   在继续之前

然后我的.RenderWithTags()方法将扩展标签,但动态执行传递的字典中的代码,例如用[HelpPage]生成的任何内容替换@Html.ActionLink(...)

我知道我可以使用Microsoft.CSharp.CSharpCodeProvider().CreateCompiler()动态编译C#代码,但Razor代码呢?

2 个答案:

答案 0 :(得分:3)

这很难做到。

相反,你应该把代表放在你的字典中 例如:

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

如果您在Razor页面中创建字典,也可以使用inline helpers

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

这将允许在值中使用任意Razor标记。

但是,我可能会建议您在代码中创建一个单一的全局字典,这样您就不需要跨页面重复定义。 (取决于您如何使用它)

答案 1 :(得分:0)

最后,解决方案变得相当光滑。没有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, "");
    }
}

评论或反馈如何最好的欢迎!