依赖注入自定义文件提供程序以进行运行时编译

Dependency inject a custom file provider for runtime compilation

我正在试验 loading views from a database,正如文章中所建议的,可能需要添加一些缓存以防止每次都访问数据库。

ConfigureServices:

services.AddHttpContextAccessor();
services.AddMemoryCache();

services.AddRazorPages()
    .AddRazorRuntimeCompilation(opt =>
    {
        opt.FileProviders.Add(new DatabaseFileProvider(Configuration["AppSettings:SQLConnectionString"]));
    });

DatabaseFileProvider构造函数:

private string _connection;

public DatabaseFileProvider(string connection)
{
    _connection = connection;
}

如何将 IMemoryCache 的实例依赖注入到 DatabaseFileProvider class?单身人士:

ConfigureServices:

services.AddSingleton<AppUtils>();

AppUtils构造函数:

private static IMemoryCache _cache;

public AppUtils(IMemoryCache cache)
{
    _cache = cache;
}

使用DI服务直接配置MvcRazorRuntimeCompilationOptions

假设目标提供商像

public class DatabaseFileProvider : IFileProvider {
    private string connection;
    private IMemoryCache cache;

    public DatabaseFileProvider(string connection, IMemoryCache cache) {
        this.connection = connection;
        this.cache = cache;
    }

    //...

}

借助 DI 服务创建提供程序将允许解析任何已注册的依赖项,并使用延迟配置委托显式注入。

引用Use DI services to configure options

services.AddHttpContextAccessor();
services.AddMemoryCache();

services
    .AddOptions<MvcRazorRuntimeCompilationOptions>() 
    .Configure<IServiceProvider>((options, sp) => { //<-- Configuration here
        var cs = Configuration["AppSettings:SQLConnectionString"]);
        var provider = ActivatorUtilities.CreateInstance<DatabaseFileProvider>(sp, cs);
        options.FileProviders.Add(provider);
    });

services.AddRazorPages()
    .AddRazorRuntimeCompilation(); //remove configuration delegate here

Configure 允许使用最多五个服务来配置选项,但如果注入 IServiceProvider,则可以根据需要使用提供程序来解决更多依赖关系。

如果该服务定位器方法不是首选,可以重新安排设置以遵循更纯粹的 DI 设计。

services.AddHttpContextAccessor();
services.AddMemoryCache();

service.AddTransient<IFileProvider, DatabaseFileProvider>(sp => {
    var cs = Configuration["AppSettings:SQLConnectionString"]);
    var provider = ActivatorUtilities.CreateInstance<DatabaseFileProvider>(sp, cs);
    return provider;
});

//... register other providers if any

services
    .AddOptions<MvcRazorRuntimeCompilationOptions>() 
    .Configure<IEnumerable<IFileProvider>>((options, providers) => {
        //add all registered providers
        foreach(IFileProvider provider in providers) {
            options.FileProviders.Add(provider);
        }
    });

services.AddRazorPages()
    .AddRazorRuntimeCompilation();