繁体   English   中英

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

[英]Loading an external .NET Standard 2.0 assembly with 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);

方法WriteSomething包含一个Console.WriteLine() ,它在浏览器的控制台中打印一些东西,这要归功于 blazor/mono.wasm 的优点。 这个库中的完整代码是:

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

结果:

chrome 控制台中的成功结果

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

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

无法加载文件或程序集“netstandard,Version=2.0.0.0,Culture=neutral,PublicKeyToken=cc7b13ffcd2ddd51”或其依赖项之一。

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

  • 将程序集加载到 AppDomain 中会产生相同的结果。
var assembly = AppDomain.CurrentDomain.Load(bytes); 
  • 切换到 netstandard 1.6 给了我一个类似的错误,这次是关于System.Runtime (因为 mono.wasm 期望Mono.Runtime我假设)。

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

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

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

我找到了解决这个问题的三种可能的方法:

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

这样,您的应用程序在构建时将自动转换为单一兼容程序集。 对 Blazor .csproj 的简单窥视显示了实现此目的所需的依赖项。 为了让它工作,我不得不改变我的外部程序集的 .csproj:

来自默认的网络标准库:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>
</Project>

进入网络应用程序:

<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>

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

有效,但感觉有点麻烦,因为我们将库转换为 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);

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

  • 无需将其更改为 Web 应用程序
  • 有效,但感觉比第一个解决方案更hacker,不确定这是否会在此过程中失败......

3. 使用 Blazor 构建工具

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

随意评论或回答其他信息。 在找到“更清洁”的解决方案之前,我将这个问题悬而未决。

这是由于 blazor 链接器剥离了对netstandard的依赖,因为它没有在主 WebAssemblyHost 项目中明确使用。

当动态加载使用netstandard的 DLL 时,它会假设它已经加载并崩溃。

如果您打算动态加载程序集,我建议使用

<BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>

以确保没有删除基本依赖项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM