美文网首页
Razorengine 的 The same key was

Razorengine 的 The same key was

作者: Sunday_1024 | 来源:发表于2022-08-10 18:52 被阅读0次

    使用razorengine 生成代码 生成报表方便。但是一旦修改模板文件cshtml,就会报错 The same key was already used for another template。查了很多资料,发现问题没那么简单。

    参考 https://github.com/Antaris/RazorEngine/issues/232

    总结原因如下:
    主要是clr机制的问题:
    1 无法卸载程序集
    2 其他动态编译方法比如说 DynamicAssemblies ,但是不能使用它
    3 没有一个好的缓存方式。

    就是说,一旦编译razor模板运行时候,模板也会编译到程序集里,但是这个模板不能修改或删除,相当于修改程序集,这个是clr不允许的事情,除非重新编译,那样相当于重启程序项目了。

    razor内部机制会有个缓存,如果模板名称没有在这个缓存中,会再次编译添加到程序集里,否则会直接用这个缓存模板。那么我改模板时候,动态添加模板名称不就行了? 但这样会导致另一个问题,如果过多的加入模板(比如说1w个),会导致程序集庞大,运行时候会因为模板在内存过多导致内存溢出。

    可能有人会说,我实现个缓存机制,如果少次数更改模板,来动态创建模板名称是否可以行。这个是可以的,但是达到量变还是会导致上面内存溢出的问题。个人感觉这个方式不是很完美,这个缓存方式有点复杂而且过于鸡肋。

    如果有人想用这个缓存方式, 可以参考如下代码:

    // 参考 https://github.com/Antaris/RazorEngine/issues/232
     public static string RazorRender(Object info, string razorTempl, string templateKey, Boolean debugMode = false)
            {
                var result = "";
                try
                {
                    var service = (IRazorEngineService)HttpContext.Current.Application.Get("NBrightBuyIRazorEngineService");
                    if (service == null)
                    {
                        // do razor test
                        var config = new TemplateServiceConfiguration();
                        config.Debug = debugMode;
                        config.BaseTemplateType = typeof(NBrightBuyRazorTokens<>);
                        service = RazorEngineService.Create(config);
                        HttpContext.Current.Application.Set("NBrightBuyIRazorEngineService", service);
                    }
                    Engine.Razor = service;
                    var israzorCached = Utils.GetCache("nbrightbuyrzcache_" + templateKey); // get a cache flag for razor compile.
                    if (israzorCached == null || (string)israzorCached != razorTempl)
                    {
                        result = Engine.Razor.RunCompile(razorTempl, GetMd5Hash(razorTempl), null, info);
                        Utils.SetCache("nbrightbuyrzcache_" + templateKey, razorTempl);
                    }
                    else
                    {
                        result = Engine.Razor.Run(GetMd5Hash(razorTempl), null, info);
                    }
    
                }
                catch (Exception ex)
                {
                    result = ex.ToString();
                }
    
                return result;
            }
    
            /// <summary>
            /// work arounf MD5 has for razorengine caching.
            /// </summary>
            /// <param name="input"></param>
            /// <returns></returns>
            private static string GetMd5Hash(string input)
            {
                var md5 = MD5.Create();
                var inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
                var hash = md5.ComputeHash(inputBytes);
                var sb = new StringBuilder();
                foreach (byte t in hash)
                {
                    sb.Append(t.ToString("X2"));
                }
                return sb.ToString();
            }
    

    总的来说,改了razor模板,只能重启程序。

    相关文章

      网友评论

          本文标题:Razorengine 的 The same key was

          本文链接:https://www.haomeiwen.com/subject/bjjtgrtx.html