From 21ea3eeb7c3e2dbb5f5b5d9adf23b6bbf0d3f7cd Mon Sep 17 00:00:00 2001 From: maliming Date: Sun, 15 Oct 2023 14:51:47 +0800 Subject: [PATCH] Fix the problem of cache `Assembly`. --- .../Razor/DefaultAbpCompiledViewProvider.cs | 17 +++++++++++++++-- .../Razor/RazorTemplateRenderingEngine.cs | 12 +++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs index 109547ada5..3658833178 100644 --- a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs @@ -4,17 +4,20 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; namespace Volo.Abp.TextTemplating.Razor; public class DefaultAbpCompiledViewProvider : IAbpCompiledViewProvider, ITransientDependency { - private static readonly ConcurrentDictionary CachedAssembles = new ConcurrentDictionary(); + private readonly static ConcurrentDictionary CachedAssembles = new ConcurrentDictionary(); + private readonly static SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1); private readonly AbpCompiledViewProviderOptions _options; private readonly AbpRazorTemplateCSharpCompiler _razorTemplateCSharpCompiler; @@ -50,7 +53,17 @@ public class DefaultAbpCompiledViewProvider : IAbpCompiledViewProvider, ITransie throw new AbpException($"Razor template content of {templateDefinition.Name} is null!"); } - return CachedAssembles.GetOrAdd((templateDefinition.Name + templateContent).ToMd5(), await CreateAssembly(templateContent)); + using (await SemaphoreSlim.LockAsync()) + { + var cacheKey = (templateDefinition.Name + templateContent).ToMd5(); + if (CachedAssembles.TryGetValue(cacheKey, out var cachedAssemble)) + { + return cachedAssemble; + } + var assemble = await CreateAssembly(templateContent); + CachedAssembles.TryAdd(cacheKey, assemble); + return assemble; + } } protected virtual async Task GetAssemblyStreamAsync(TemplateDefinition templateDefinition, string templateContent) diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs index 86298f2daf..216b72a6bf 100644 --- a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs @@ -18,18 +18,15 @@ public class RazorTemplateRenderingEngine : TemplateRenderingEngineBase, ITransi public override string Name => EngineName; protected readonly IServiceScopeFactory ServiceScopeFactory; - protected readonly IAbpCompiledViewProvider AbpCompiledViewProvider; public RazorTemplateRenderingEngine( IServiceScopeFactory serviceScopeFactory, - IAbpCompiledViewProvider abpCompiledViewProvider, ITemplateDefinitionManager templateDefinitionManager, ITemplateContentProvider templateContentProvider, IStringLocalizerFactory stringLocalizerFactory) : base(templateDefinitionManager, templateContentProvider, stringLocalizerFactory) { ServiceScopeFactory = serviceScopeFactory; - AbpCompiledViewProvider = abpCompiledViewProvider; } public override async Task RenderAsync( @@ -115,12 +112,13 @@ public class RazorTemplateRenderingEngine : TemplateRenderingEngineBase, ITransi Dictionary globalContext, object model = null) { - var assembly = await AbpCompiledViewProvider.GetAssemblyAsync(templateDefinition); - var templateType = assembly.GetType(AbpRazorTemplateConsts.TypeName); - var template = (IRazorTemplatePage)Activator.CreateInstance(templateType); - using (var scope = ServiceScopeFactory.CreateScope()) { + var compiledViewProvider = scope.ServiceProvider.GetRequiredService(); + var assembly = await compiledViewProvider.GetAssemblyAsync(templateDefinition); + var templateType = assembly.GetType(AbpRazorTemplateConsts.TypeName); + var template = (IRazorTemplatePage)Activator.CreateInstance(templateType); + var modelType = templateType .GetInterfaces() .Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IRazorTemplatePage<>))