V11: Fix InMemoryAuto modelsbuilder mode (#13107)
* POC of a solution that works * Add razor reference manager * Ensure the compilation options are correct * Move InMemory classes to its own namespace These are all internal, so it should be fine. * Throw proper exceptions when compilation fails * Add CheckSumValidator * Clear the ViewCompiler cache when models changed This means we no longer need the RefreshingRazorViewEngine \o/ * Remove unused constructor injection * Make UmbracoAssemblyLoadContext non internal * Add WIP * Clear the RazorViewEngine cache when generating new models This uses reflection, which isn't super nice, however, the alternative is to clone'n'own the entire RazorViewEngine, which is arguably worse * Fix circular dependency * Remove ModelsChanged event This is no longer necessary * Fix precompiled views path We need to normalize these paths to ensure they matches with the keys in _precompiledViews * Clean * Fix content tests * Add logging * Update the comment in UmbracoBuilderDependencyInjectionExtensions to reflect changes * Remove RefreshingRazorViewEngine as its no longer needed * Remove unused ViewEngine hack from DI * Fix langversion This is required since dotnet 7 is still in preview * Add modelsbuilder tests * Add more tests * fixed comment Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using Umbraco.Cms.Infrastructure.ModelsBuilder;
|
||||
|
||||
namespace Umbraco.Cms.Web.Common.ModelsBuilder.InMemoryAuto;
|
||||
|
||||
internal class InMemoryAssemblyLoadContextManager
|
||||
{
|
||||
private UmbracoAssemblyLoadContext? _currentAssemblyLoadContext;
|
||||
|
||||
public InMemoryAssemblyLoadContextManager() =>
|
||||
AssemblyLoadContext.Default.Resolving += OnResolvingDefaultAssemblyLoadContext;
|
||||
|
||||
private string? _modelsAssemblyLocation;
|
||||
|
||||
public string? ModelsAssemblyLocation => _modelsAssemblyLocation;
|
||||
|
||||
/// <summary>
|
||||
/// Handle the event when a reference cannot be resolved from the default context and return our custom MB assembly reference if we have one
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is required because the razor engine will only try to load things from the default context, it doesn't know anything
|
||||
/// about our context so we need to proxy.
|
||||
/// </remarks>
|
||||
private Assembly? OnResolvingDefaultAssemblyLoadContext(AssemblyLoadContext assemblyLoadContext, AssemblyName assemblyName)
|
||||
=> assemblyName.Name == RoslynCompiler.GeneratedAssemblyName
|
||||
? _currentAssemblyLoadContext?.LoadFromAssemblyName(assemblyName)
|
||||
: null;
|
||||
|
||||
internal void RenewAssemblyLoadContext()
|
||||
{
|
||||
// If there's a current AssemblyLoadContext, unload it before creating a new one.
|
||||
_currentAssemblyLoadContext?.Unload();
|
||||
|
||||
// We must create a new assembly load context
|
||||
// as long as theres a reference to the assembly load context we can't delete the assembly it loaded
|
||||
_currentAssemblyLoadContext = new UmbracoAssemblyLoadContext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads an assembly into the collectible assembly used by the factory
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is essentially just a wrapper around the <see cref="UmbracoAssemblyLoadContext"/>,
|
||||
/// because we don't want to allow other clases to take a reference on the AssemblyLoadContext
|
||||
/// </remarks>
|
||||
/// <returns>The loaded assembly</returns>
|
||||
public Assembly LoadCollectibleAssemblyFromStream(Stream assembly, Stream? assemblySymbols)
|
||||
{
|
||||
_currentAssemblyLoadContext ??= new UmbracoAssemblyLoadContext();
|
||||
return _currentAssemblyLoadContext.LoadFromStream(assembly, assemblySymbols);
|
||||
}
|
||||
|
||||
public Assembly LoadCollectibleAssemblyFromPath(string path)
|
||||
{
|
||||
_currentAssemblyLoadContext ??= new UmbracoAssemblyLoadContext();
|
||||
return _currentAssemblyLoadContext.LoadFromAssemblyPath(path);
|
||||
}
|
||||
|
||||
public Assembly LoadModelsAssembly(string path)
|
||||
{
|
||||
Assembly assembly = LoadCollectibleAssemblyFromPath(path);
|
||||
_modelsAssemblyLocation = assembly.Location;
|
||||
return assembly;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user