LibSassHost
LibSassHost copied to clipboard
request: non-static file manager
Hello! I'm building a web application that uses LibSassHost. The one issue I ran into is that to specify a file manager, I have to plug it into the static property SassCompiler.FileManager
. However, when you have multiple users on a website, each user may have different values current directory, folders and files available.
I considered using locks, though that would be a nasty quick that makes each user wait for everybody else. Slim semaphores would be better than locks, because they release threads, but still would make each user wait in line.
The ideal scenario would be to be able to pass the file manager in the parameter options of the compiler.
I think I found a workaround using AsyncLocal.
Hello, Pablo!
The ideal scenario would be to be able to pass the file manager in the parameter options of the compiler.
I myself would be happy to implement this functionality, but I do not have such an opportunity due to architectural limitations of original library.
Understood. In my case I am using ASP.NET Core and because of that I was able work around this using AsyncLocal. This lets you create static variables that have different values on each HTTP request. So, my static class has a different set of values populated for each user, and there is no locking involved.
Excellent!
Below is a wrapper that instantiates a different IFileManager
on each async flow. To use it, we simply call GlobalFileManager.LocalManager = myInstance
using LibSassHost;
using System.Threading;
namespace Integrative.ModelerEngine.Styles
{
class GlobalFileManager : IFileManager
{
readonly static GlobalFileManager _instance = new GlobalFileManager();
readonly static AsyncLocal<IFileManager> _local = new AsyncLocal<IFileManager>();
readonly static object _lock = new object();
private GlobalFileManager()
{
}
public static IFileManager LocalManager
{
get => _local.Value;
set
{
InitializeGlobal();
_local.Value = value;
}
}
private static void InitializeGlobal()
{
if (SassCompiler.FileManager == _instance)
{
return;
}
lock (_lock)
{
if (SassCompiler.FileManager != _instance) // check again under lock
{
SassCompiler.FileManager = _instance;
}
}
}
public bool SupportsConversionToAbsolutePath
=> _local.Value.SupportsConversionToAbsolutePath;
public string GetCurrentDirectory()
{
return _local.Value.GetCurrentDirectory();
}
public bool FileExists(string path)
{
return _local.Value.FileExists(path);
}
public bool IsAbsolutePath(string path)
{
return _local.Value.IsAbsolutePath(path);
}
public string ToAbsolutePath(string path)
{
return _local.Value.ToAbsolutePath(path);
}
public string ReadFile(string path)
{
return _local.Value.ReadFile(path);
}
}
}
Hello, Pablo!
The ideal scenario would be to be able to pass the file manager in the parameter options of the compiler.
At the moment, I recommend that you switch to a Dart Sass Host library that supports this feature.