动态 Razor 代码执行 - 如何?

发布于 2024-11-11 11:26:36 字数 680 浏览 1 评论 0原文

这篇文章中,我想知道更干净的代码当应用程序国际化时。这导致了第二个查询...假设我想调用这样的函数:

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

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

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

,我的 .RenderWithTags() 方法将扩展标签,但动态执行传递的字典中的代码,例如将 [HelpPage] 替换为任何 @Html.ActionLink(...)< /code> 产生。

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

In this post I wondered about cleaner code when internationalising an app. that leads to this second query... supposing I wanted to call a function like this:

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

such that I look up a string in my local resource file containing embedded "tags" e.g. resource name "Help" contains:

We suggest you read our [HelpPage]
before proceeding

and then my .RenderWithTags() method will expand the tags but dynamically executing the code in the dictionary passed e.g. replace [HelpPage] with whatever @Html.ActionLink(...) produces.

I know I can use Microsoft.CSharp.CSharpCodeProvider().CreateCompiler() to compile C# code on the fly, but what about Razor code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

醉梦枕江山 2024-11-18 11:26:36

这将是相当困难的。

相反,您应该将代表放入您的字典中。
例如:

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

如果您在 Razor 页面中创建字典,则还可以使用 内联助手

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

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

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

This will be rather difficult to do.

Instead, you should put delegates in your dictionary.
For example:

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

If you're creating the dictionary in a Razor page, you could also use inline helpers:

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

This will allow to use arbitrary Razor markup in the values.

However, I would probably recommend that you create a single global dictionary in code, so that you don't need to repeat definitions across pages. (Depending on how you use it)

|煩躁 2024-11-18 11:26:36

最后,解决方案变得非常巧妙。如果没有 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, "");
    }
}

关于如何做得更好的评论或反馈,最受欢迎!

in the end, the solution turned out pretty slick. would not have been possible without SLaks, I'm much obliged for the help (though I didn't end up using inline helpers (but thanks for the intro (they're very cool))).
Now my page contains this:

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

and somewhere below I have:

@this.Resource("Epilogue", tokenMap)

To accomplish this simplicity:

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

...and:

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

...with a little extra help:

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, "");
    }
}

comments or feedback on how it could have been better most welcome!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文