gpt4 book ai didi

c# - 添加要在运行时对 Razor 页面可用的程序集/类型

转载 作者:太空宇宙 更新时间:2023-11-03 14:38:45 35 4
gpt4 key购买 nike

我正在尝试构建一个动态 Web 界面,我可以在其中动态指向一个文件夹并使用 ASP.NET Core 从该文件夹提供 Web 内容。通过使用 ASP.NET Core 中的 FileProvider 重新路由 Web 根文件夹,这很容易实现。这适用于 StaticFiles 和 RazorPages。

但是,对于 RazorPages,问题在于一旦执行此操作,就无法动态添加对其他类型的引用。我希望能够有选择地添加一个文件夹 (PrivateBin),在启动时我可以循环访问它,加载程序集,然后让这些程序集在 Razor 中可见。

不幸的是,它不起作用,因为即使在使用运行时编译时,Razor 似乎也看不到加载的程序集。

我在启动期间使用以下内容来加载程序集。请注意,从中加载这些文件的文件夹不在默认的 ContentRoot 或 WebRoot 中,而是在新的重定向 WebRoot 中。

// WebRoot is a user chosen Path here specified via command line --WebRoot c:\temp\web
private void LoadPrivateBinAssemblies()
{
var binPath = Path.Combine(WebRoot, "PrivateBin");
if (Directory.Exists(binPath))
{
var files = Directory.GetFiles(binPath);
foreach (var file in files)
{
if (!file.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase) &&
!file.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))
continue;

try
{
var asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(file);
Console.WriteLine("Additional Assembly: " + file);
}
catch (Exception ex)
{
Console.WriteLine("Failed to load private assembly: " + file);
}
}
}
}

程序集加载到 AssemblyLoadContext() 中,我可以 - 使用反射和 Type.GetType("namespace.class,assembly") - 访问类型。

但是,当我尝试访问 RazorPages 中的类型时 - 即使启用了运行时编译 - 这些类型也不可用。我收到以下错误:

enter image description here

为了确保该类型确实可用,我检查了我是否可以在 Razor 内部执行以下操作:

@{
var md = Type.GetType("Westwind.AspNetCore.Markdown.Markdown,Westwind.AspNetCore.Markdown");
var mdText = md.InvokeMember("Parse", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null,
null, new object[] { "**asdasd**", false, false, false });
}
@mdText

而且效果很好。因此程序集已加载且类型可访问,但 Razor 似乎没有意识到这一点。

所以问题是:

是否可以在运行时加载程序集并通过运行时编译使它们对 Razor 可用,并像通常通过直接声明访问使用类型一样使用它?

最佳答案

事实证明,这个问题的解决方案是通过 Razor 运行时编译选项,它允许添加额外的“ReferencePaths”,然后显式加载程序集。

在 ConfigureServices() 中:

services.AddRazorPages(opt => { opt.RootDirectory = "/"; })
.AddRazorRuntimeCompilation(
opt =>
{

opt.FileProviders.Add(new PhysicalFileProvider(WebRoot));
LoadPrivateBinAssemblies(opt);
});

然后:

private void LoadPrivateBinAssemblies(MvcRazorRuntimeCompilationOptions opt)
{
var binPath = Path.Combine(WebRoot, "PrivateBin");
if (Directory.Exists(binPath))
{
var files = Directory.GetFiles(binPath);
foreach (var file in files)
{
if (!file.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase) &&
!file.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))
continue;

try
{
var asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(file);
opt.AdditionalReferencePaths.Add(file);
}
catch (Exception ex)
{
...
}

}
}

}

关键是:

opt.AdditionalReferencePaths.Add(file);  

这使程序集对 Razor 可见,但实际上并不加载它。要加载它,您必须显式加载它:

AssemblyLoadContext.Default.LoadFromAssemblyPath(file);

从路径加载程序集。请注意,此程序集所具有的任何依赖项都必须在应用程序的启动路径中或在您从中加载的同一文件夹中可用。

Note: Load order for dependencies may be important here or a not previously added assembly may not be found as a dependency (untested).

关于c# - 添加要在运行时对 Razor 页面可用的程序集/类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58685966/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com