使用blazor加载外部.NET Standard 2.0程序集

Sig*_*gge 6 c# webassembly asp.net-core .net-standard blazor

在Blazor应用程序中,我想加载外部程序集并执行方法。为此,我使用Blazor模板创建了一个新的ASP.Net Core Web应用程序。

然后,在Razor页面(将由浏览器/ wasm编译并执行)中,我使用反射来加载程序集并运行方法(基于此处找到的代码)

// download external assembly from server
HttpClient client = new HttpClient();
var bytes = await client.GetByteArrayAsync("http://localhost:62633/_framework/MyCustomLib.dll");

//load assembly
var assembly = System.Reflection.Assembly.Load(bytes);

// get type/method info
var type = assembly.GetType("MyCustomLib.MyCustomClass");
var method = type.GetMethod("WriteSomething");

// instantiate object and run method
object classInstance = Activator.CreateInstance(type, null);
method.Invoke(classInstance, null);
Run Code Online (Sandbox Code Playgroud)

由于blazor / mono.wasm的优点,该方法WriteSomething包含一个Console.WriteLine()可在浏览器的控制台中打印内容的代码。该库中的完整代码为:

namespace MyCustomLib
{
    public class MyCustomClass
    {
        public void WriteSomething()
        {
            System.Console.WriteLine("This is printed from a loaded dll 3 !");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

chrome控制台成功的结果

如您所见,当MyCustomLib.dll被构建为.NET Framework类库时,这非常有用。但是,我想使用.NET标准类库。

当我构建一个MyCustomLib.dll.NET Standard 2.0库并执行相同的blazor应用程序时,在浏览器的控制台中出现以下错误:

无法加载文件或程序集“ netstandard,版本= 2.0.0.0,区域性=中性,PublicKeyToken = cc7b13ffcd2ddd51”或其依赖项之一。

我希望mono.wasm会加载必要的依赖项以支持.NET Standard程序集。

  • 将程序集加载到AppDomain中会产生相同的结果。
var assembly = AppDomain.CurrentDomain.Load(bytes); 
Run Code Online (Sandbox Code Playgroud)
  • 这次切换到netstandard 1.6会给我一个类似的错误System.Runtime(因为mono.wasm期望Mono.Runtime我承担)。

  • 也许有一种方法可以LoadAssembly对netstandard2.0包引用的程序集执行操作,但是我不知道如何执行。

如何使用Blazor将.NET Standard 2.0加载到浏览器环境中?

Sig*_*gge 4

经过进一步调查后,我得出的结论是,我的问题是我的外部库未正确链接到 mono.net 依赖项。这就是为什么当您构建 Blazor 应用程序时,它会第二次编译到 /dist/_framework/_bin。

我发现了这个问题的三种可能的解决方案:

1.将外部类库变成Blazor Web应用程序

这样,您的应用程序在构建时将自动转换为单兼容程序集。简单查看 Blazor .csproj 即可了解实现此目的所需的依赖项。为了让它工作,我必须更改外部程序集的 .csproj:

来自默认的网络标准库:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

进入网络应用程序:

<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <RunCommand>dotnet</RunCommand>
        <LangVersion>7.3</LangVersion>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="0.7.0" PrivateAssets="all" />
    </ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

这些是唯一需要的依赖项。构建时,将在 /dist/_framework/_bin 文件夹中找到兼容的程序集。然后可以使用问题中描述的方法加载它。

可行,但感觉有点 hacky,因为我们将库转变为 Web 应用程序的唯一原因是它可以将自身编译成正确链接的程序集。

2.加载netstandard2.0 mono外观

另一个解决方案是从Microsoft.AspNetCore.Blazor.Build解压缩 Nuget 包并获取 netstandard.dll。可以在文件夹中找到它tools\mono\bcl\Facades。现在,在主 Blazor 应用程序中执行以下操作时:

var netstandard = await client.GetByteArrayAsync("http://localhost:62633/_framework/netstandard.dll");
var externallib = await client.GetByteArrayAsync("http://localhost:62633/_framework/MyCustomLib.dll");
AppDomain.CurrentDomain.Load(netstandard);
var assembly = AppDomain.CurrentDomain.Load(externallib);
Run Code Online (Sandbox Code Playgroud)

那么未修改的netstandard 2.0 库MyCustomLib将被正确加载。

  • 无需将其更改为网络应用程序
  • 可行,但感觉比第一个解决方案更黑客,不确定这是否会在以后失败......

3.使用 Blazor 构建工具

Blazor 构建工具,目前可以在此处找到,它们有一个ResolveRuntimeDependenciesCommandCLI 命令,该命令似乎与 blazor Web 应用程序将输出吐出到 /_framework/_bin 时所做的完全一样。我仍在研究如何使用它将“非 blazor-webapp”程序集转换为单兼容程序集。

请随意发表评论或回答更多信息。在找到“更干净”的解决方案之前,我将保留这个问题。