Współdziałanie języka JavaScript [JSImport]
/[JSExport]
z projektem aplikacji webAssembly Browser
Uwaga
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Ważne
Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
W tym artykule wyjaśniono, jak skonfigurować projekt aplikacji przeglądarki WebAssembly w celu uruchamiania platformy .NET z poziomu języka JavaScript (JS) przy użyciu/JS[JSImport]
[JSExport]
międzyoperacji. Aby uzyskać dodatkowe informacje i przykłady, zobacz Międzyoperacja języka JavaScript "[JSImport]"/"[JSExport]" w zestawie webAssembly platformy .NET.
Aby uzyskać dodatkowe wskazówki, zobacz wskazówki dotyczące konfigurowania i hostowania aplikacji webAssembly platformy .NET w repozytorium GitHub Runtime (dotnet/runtime
).
Istniejące JS aplikacje mogą używać rozszerzonej obsługi zestawu WebAssembly po stronie klienta w celu ponownego użycia bibliotek platformy .NET z JS lub do kompilowania nowatorskich elementów . Aplikacje i struktury oparte na platformie NET.
Uwaga
Ten artykuł koncentruje się na uruchamianiu platformy .NET z JS poziomu aplikacji bez żadnej zależności od Blazorprogramu . Aby uzyskać wskazówki dotyczące korzystania z [JSImport]
/[JSExport]
międzyoperacji w Blazor WebAssembly aplikacjach, zobacz JavaScript JSImport/JSExport interop with ASP.NET Core .Blazor
Te podejścia są odpowiednie, gdy oczekujesz Blazor , że aplikacja zostanie uruchomiona tylko w zestawie WebAssembly (WASM). Biblioteki mogą sprawdzić środowisko uruchomieniowe, aby określić, czy aplikacja jest uruchomiona WASM , wywołując polecenie OperatingSystem.IsBrowser.
Wymagania wstępne
Zestaw .NET SDK (najnowsza wersja)
wasm-tools
Zainstaluj obciążenie w administracyjnej powłoce poleceń, co powoduje wprowadzenie powiązanych elementów docelowych programu MSBuild:
dotnet workload install wasm-tools
Narzędzia można również zainstalować za pomocą instalatora programu Visual Studio w ramach obciążenia ASP.NET i tworzenia aplikacji internetowych w instalatorze programu Visual Studio. Wybierz opcję Narzędzia kompilacji zestawu WebAssembly platformy .NET z listy składników opcjonalnych.
Opcjonalnie zainstaluj wasm-experimental
obciążenie, które dodaje następujące eksperymentalne szablony projektów:
- Aplikacja przeglądarki WebAssembly na potrzeby rozpoczynania pracy z platformą .NET w zestawie WebAssembly w aplikacji przeglądarki.
- Aplikacja konsolowa zestawu WebAssembly na potrzeby rozpoczynania pracy w węźle.js- oparta na aplikacji konsolowej.
Po zainstalowaniu obciążenia można wybrać te nowe szablony podczas tworzenia nowego projektu. To obciążenie nie jest wymagane, jeśli planujesz integrację JS[JSExport]
[JSImport]
/międzyoperacji z istniejącą JS aplikacją.
dotnet workload install wasm-experimental
Szablony można również zainstalować z Microsoft.NET.Runtime.WebAssembly.Templates
pakietu NuGet za pomocą następującego polecenia:
dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates
Aby uzyskać więcej informacji, zobacz sekcję Eksperymentalne obciążenie i szablony projektów.
Przestrzeń nazw
Interfejs JS API międzyoperacyjnych opisany w tym artykule jest kontrolowany przez atrybuty w System.Runtime.InteropServices.JavaScript przestrzeni nazw.
Konfiguracja projektu
Aby skonfigurować projekt (.csproj
) w celu włączenia JS międzyoperacjności:
Ustaw moniker platformy docelowej (
{TARGET FRAMEWORK}
symbol zastępczy):<TargetFramework>{TARGET FRAMEWORK}</TargetFramework>
Obsługiwana jest platforma .NET 7 (
net7.0
) lub nowsza wersja.AllowUnsafeBlocks Włącz właściwość , która zezwala generatorowi kodu w kompilatorze Roslyn na używanie wskaźników dla JS międzyoperacyjności:
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Ostrzeżenie
Interfejs JS API międzyoperajności wymaga włączenia funkcji AllowUnsafeBlocks. Należy zachować ostrożność podczas implementowania własnego niebezpiecznego kodu w aplikacjach platformy .NET, co może powodować zagrożenia bezpieczeństwa i stabilności. Aby uzyskać więcej informacji, zobacz Niebezpieczny kod, typy wskaźników i wskaźniki funkcji.
Poniżej przedstawiono przykładowy plik projektu (.csproj
) po konfiguracji. Symbol {TARGET FRAMEWORK}
zastępczy to struktura docelowa:
<Project Sdk="Microsoft.NET.Sdk.WebAssembly">
<PropertyGroup>
<TargetFramework>{TARGET FRAMEWORK}</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>
Ustaw moniker platformy docelowej:
<TargetFramework>net7.0</TargetFramework>
Obsługiwana jest platforma .NET 7 (
net7.0
) lub nowsza wersja.Określ
browser-wasm
identyfikator środowiska uruchomieniowego:<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
Określ typ danych wyjściowych pliku wykonywalnego:
<OutputType>Exe</OutputType>
AllowUnsafeBlocks Włącz właściwość , która zezwala generatorowi kodu w kompilatorze Roslyn na używanie wskaźników dla JS międzyoperacyjności:
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Ostrzeżenie
Interfejs JS API międzyoperajności wymaga włączenia funkcji AllowUnsafeBlocks. Należy zachować ostrożność podczas implementowania własnego niebezpiecznego kodu w aplikacjach platformy .NET, co może powodować zagrożenia bezpieczeństwa i stabilności. Aby uzyskać więcej informacji, zobacz Niebezpieczny kod, typy wskaźników i wskaźniki funkcji.
Określ
WasmMainJSPath
, aby wskazać plik na dysku. Ten plik jest publikowany w aplikacji, ale użycie pliku nie jest wymagane, jeśli integrujesz platformę .NET z istniejącą JS aplikacją.W poniższym przykładzie JS plik na dysku to
main.js
, ale dowolna JS nazwa pliku jest permissable:<WasmMainJSPath>main.js</WasmMainJSPath>
Przykładowy plik projektu (.csproj
) po konfiguracji:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<WasmMainJSPath>main.js</WasmMainJSPath>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Interopcja języka JavaScript w systemie WASM
Interfejsy API w poniższym przykładzie są importowane z dotnet.js
usługi . Te interfejsy API umożliwiają skonfigurowanie nazwanych modułów, które można zaimportować do kodu języka C# i wywołać do metod uwidocznionych przez kod platformy .NET, w tym Program.Main
.
Ważne
"Import" i "export" w tym artykule są definiowane z perspektywy platformy .NET:
- Aplikacja importuje JS metody, aby można je było wywołać z platformy .NET.
- Aplikacja eksportuje metody .NET, aby można je było wywołać z JS.
W poniższym przykładzie:
Plik
dotnet.js
jest używany do tworzenia i uruchamiania środowiska uruchomieniowego zestawu WebAssembly platformy .NET.dotnet.js
jest generowany jako część danych wyjściowych kompilacji aplikacji.Ważne
Aby zintegrować z istniejącą aplikacją, skopiuj zawartość folderu wyjściowego publikowania† do zasobów wdrożenia istniejącej aplikacji, aby można było ją obsłużyć wraz z aplikacją rest . W przypadku wdrożeń produkcyjnych opublikuj aplikację za pomocą
dotnet publish -c Release
polecenia w powłoce poleceń i wdróż zawartość folderu wyjściowego za pomocą aplikacji.† Folder wyjściowy publikowania jest lokalizacją docelową profilu publikowania. Domyślnym ustawieniem Release profilu na platformie .NET 8 lub nowszym jest
bin/Release/{TARGET FRAMEWORK}/publish
, gdzie{TARGET FRAMEWORK}
symbol zastępczy to platforma docelowa (na przykładnet8.0
).dotnet.create()
Konfiguruje środowisko uruchomieniowe zestawu webAssembly platformy .NET.
setModuleImports
kojarzy nazwę z modułem JS funkcji do importowania do platformy .NET. Moduł JS zawieradom.setInnerText
funkcję, która akceptuje selektor elementów i czas wyświetlania bieżącego czasu stopera w interfejsie użytkownika. Nazwa modułu może być dowolnym ciągiem (nie musi być nazwą pliku), ale musi być zgodna z nazwą używaną z wartościąJSImportAttribute
(wyjaśnionej w dalszej części tego artykułu). Funkcjadom.setInnerText
jest importowana do języka C# i wywoływana przez metodęSetInnerText
języka C#. Metoda jest wyświetlanaSetInnerText
w dalszej części tej sekcji.exports.StopwatchSample.Reset()
wywołania do platformy .NET (StopwatchSample.Reset
) z JS.Reset
Metoda języka C# uruchamia stoper, jeśli jest uruchomiony lub resetuje go, jeśli nie jest uruchomiony. Metoda jest wyświetlanaReset
w dalszej części tej sekcji.exports.StopwatchSample.Toggle()
wywołania do platformy .NET (StopwatchSample.Toggle
) z JS. MetodaToggle
języka C# uruchamia lub zatrzymuje stoper w zależności od tego, czy jest aktualnie uruchomiony, czy nie. Metoda jest wyświetlanaToggle
w dalszej części tej sekcji.runMain()
uruchamia polecenieProgram.Main
.
setModuleImports
kojarzy nazwę z modułem JS funkcji do importowania do platformy .NET. Moduł JS zawierawindow.location.href
funkcję, która zwraca bieżący adres strony (adres URL). Nazwa modułu może być dowolnym ciągiem (nie musi być nazwą pliku), ale musi być zgodna z nazwą używaną z wartościąJSImportAttribute
(wyjaśnionej w dalszej części tego artykułu). Funkcjawindow.location.href
jest importowana do języka C# i wywoływana przez metodęGetHRef
języka C#. Metoda jest wyświetlanaGetHRef
w dalszej części tej sekcji.exports.MyClass.Greeting()
wywołania do platformy .NET (MyClass.Greeting
) z JS. MetodaGreeting
języka C# zwraca ciąg, który zawiera wynik wywołaniawindow.location.href
funkcji. Metoda jest wyświetlanaGreeting
w dalszej części tej sekcji.dotnet.run()
uruchamia polecenieProgram.Main
.
JS moduł:
import { dotnet } from './_framework/dotnet.js'
const { setModuleImports, getAssemblyExports, getConfig, runMain } = await dotnet
.withApplicationArguments("start")
.create();
setModuleImports('main.js', {
dom: {
setInnerText: (selector, time) =>
document.querySelector(selector).innerText = time
}
});
const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
document.getElementById('reset').addEventListener('click', e => {
exports.StopwatchSample.Reset();
e.preventDefault();
});
const pauseButton = document.getElementById('pause');
pauseButton.addEventListener('click', e => {
const isRunning = exports.StopwatchSample.Toggle();
pauseButton.innerText = isRunning ? 'Pause' : 'Start';
e.preventDefault();
});
await runMain();
import { dotnet } from './_framework/dotnet.js'
const { setModuleImports, getAssemblyExports, getConfig } = await dotnet
.withDiagnosticTracing(false)
.withApplicationArgumentsFromQuery()
.create();
setModuleImports('main.js', {
window: {
location: {
href: () => globalThis.window.location.href
}
}
});
const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
const text = exports.MyClass.Greeting();
console.log(text);
document.getElementById('out').innerHTML = text;
await dotnet.run();
import { dotnet } from './dotnet.js'
const is_browser = typeof window != "undefined";
if (!is_browser) throw new Error(`Expected to be running in a browser`);
const { setModuleImports, getAssemblyExports, getConfig } =
await dotnet.create();
setModuleImports("main.js", {
window: {
location: {
href: () => globalThis.window.location.href
}
}
});
const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
const text = exports.MyClass.Greeting();
console.log(text);
document.getElementById("out").innerHTML = text;
await dotnet.run();
Aby zaimportować JS funkcję, aby można ją było wywołać z języka C#, należy użyć jej w JSImportAttribute podpisie zgodnej metody. Pierwszy parametr JSImportAttribute to nazwa JS funkcji do zaimportowania, a drugi parametr to nazwa modułu.
W poniższym przykładzie dom.setInnerText
funkcja jest wywoływana z modułu main.js
, gdy SetInnerText
wywoływana jest metoda:
[JSImport("dom.setInnerText", "main.js")]
internal static partial void SetInnerText(string selector, string content);
W poniższym przykładzie window.location.href
funkcja jest wywoływana z modułu main.js
, gdy GetHRef
wywoływana jest metoda:
[JSImport("window.location.href", "main.js")]
internal static partial string GetHRef();
W zaimportowanym podpisie metody można użyć typów platformy .NET dla parametrów i wartości zwracanych, które są automatycznie obsługiwane przez środowisko uruchomieniowe. Służy JSMarshalAsAttribute<T> do kontrolowania sposobu stosowania importowanych parametrów metody. Na przykład możesz wybrać przeprowadzanie marshalingu long
jako lub System.Runtime.InteropServices.JavaScript.JSType.BigIntSystem.Runtime.InteropServices.JavaScript.JSType.Number . Wywołania zwrotne można przekazać Action/Func<TResult> jako parametry, które są wywoływane jako funkcje możliwe do wywołania.JS Można przekazać odwołania do JS obiektów zarządzanych i i są one marshalowane jako obiekty proxy, utrzymując obiekt aktywny przez granicę do momentu, aż serwer proxy zostanie odśmiecany. Możesz również importować i eksportować metody asynchroniczne z Task wynikiem, które są marshalowane jako JS obietnice. Większość typów marshalled działa w obu kierunkach, jako parametry i jako wartości zwracane, zarówno w metodach importowanych, jak i eksportowanych.
Aby uzyskać dodatkowe informacje o mapowaniu typów i przykłady, zobacz Interop języka JavaScript "[JSImport]"/"[JSExport]" w zestawie webAssembly platformy .NET.
Funkcje dostępne w globalnej przestrzeni nazw można importować przy użyciu prefiksu globalThis
w nazwie funkcji i przy użyciu atrybutu bez podawania nazwy modułu [JSImport]
. W poniższym przykładzie console.log
element ma prefiks globalThis
. Zaimportowana funkcja jest wywoływana przez metodę języka C#, która akceptuje komunikat ciągu języka C# Log
(message
) i marshalls ciąg języka C# dla JSString
elementu :console.log
[JSImport("globalThis.console.log")]
internal static partial void Log([JSMarshalAs<JSType.String>] string message);
Aby wyeksportować metodę .NET, aby można ją było wywołać z JSklasy , użyj polecenia JSExportAttribute.
W poniższym przykładzie każda metoda jest eksportowana do JS funkcji i może być wywoływana z JS funkcji:
- Metoda
Toggle
uruchamia lub zatrzymuje stoper w zależności od jego stanu działania. - Metoda
Reset
ponownie uruchamia stoper, jeśli jest uruchomiony lub resetuje go, jeśli nie jest uruchomiony. - Metoda
IsRunning
wskazuje, czy stoper jest uruchomiony.
[JSExport]
internal static bool Toggle()
{
if (stopwatch.IsRunning)
{
stopwatch.Stop();
return false;
}
else
{
stopwatch.Start();
return true;
}
}
[JSExport]
internal static void Reset()
{
if (stopwatch.IsRunning)
stopwatch.Restart();
else
stopwatch.Reset();
Render();
}
[JSExport]
internal static bool IsRunning() => stopwatch.IsRunning;
W poniższym przykładzie Greeting
metoda zwraca ciąg zawierający wynik wywołania GetHRef
metody . Jak pokazano wcześniej, GetHref
metoda języka C# wywołuje JS funkcję window.location.href
z modułu main.js
. window.location.href
Zwraca bieżący adres strony (adres URL):
[JSExport]
internal static string Greeting()
{
var text = $"Hello, World! Greetings from {GetHRef()}";
Console.WriteLine(text);
return text;
}
Eksperymentalne szablony obciążeń i projektów
Aby zademonstrować JS funkcjonalność międzyoperajności i uzyskać JS szablony projektów międzyoperajowych, zainstaluj wasm-experimental
obciążenie:
dotnet workload install wasm-experimental
Obciążenie wasm-experimental
zawiera dwa szablony projektów: wasmbrowser
i wasmconsole
. Te szablony są obecnie eksperymentalne, co oznacza, że przepływ pracy dewelopera dla szablonów ewoluuje. Jednak platformy .NET i JS interfejsy API używane w szablonach są obsługiwane na platformie .NET 8 i stanowią podstawę do korzystania z platformy .NET na WASM platformie JS.
Szablony można również zainstalować z Microsoft.NET.Runtime.WebAssembly.Templates
pakietu NuGet za pomocą następującego polecenia:
dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates
Aplikacja przeglądarki
Aplikację przeglądarki można utworzyć przy użyciu szablonu wasmbrowser
z poziomu wiersza polecenia, która tworzy aplikację internetową, która demonstruje korzystanie z platformy .NET i JS razem w przeglądarce:
dotnet new wasmbrowser
Alternatywnie w programie Visual Studio możesz utworzyć aplikację przy użyciu szablonu WebAssembly Browser App projektu.
Skompiluj aplikację z programu Visual Studio lub przy użyciu interfejsu wiersza polecenia platformy .NET:
dotnet build
Skompiluj i uruchom aplikację z poziomu programu Visual Studio lub przy użyciu interfejsu wiersza polecenia platformy .NET:
dotnet run
Alternatywnie zainstaluj polecenie i użyj polecenia dotnet serve
:
dotnet serve -d:bin/$(Configuration)/{TARGET FRAMEWORK}/publish
W poprzednim przykładzie {TARGET FRAMEWORK}
symbol zastępczy jest pseudonimem platformy docelowej.
Węzeł.js aplikacja konsolowa
Aplikację konsolową można utworzyć przy użyciu szablonuwasmconsole
, który tworzy aplikację działającą w obszarze WASM jako węzełjs lub aplikację konsolową w wersji 8:
dotnet new wasmconsole
Alternatywnie w programie Visual Studio możesz utworzyć aplikację przy użyciu szablonu WebAssembly Console App projektu.
Skompiluj aplikację z programu Visual Studio lub przy użyciu interfejsu wiersza polecenia platformy .NET:
dotnet build
Skompiluj i uruchom aplikację z poziomu programu Visual Studio lub przy użyciu interfejsu wiersza polecenia platformy .NET:
dotnet run
Alternatywnie uruchom dowolny statyczny serwer plików z katalogu wyjściowego publikowania, który zawiera main.mjs
plik:
node bin/$(Configuration)/{TARGET FRAMEWORK}/{PATH}/main.mjs
W poprzednim przykładzie {TARGET FRAMEWORK}
symbol zastępczy jest pseudonimem platformy docelowej, a {PATH}
symbol zastępczy jest ścieżką main.mjs
do pliku.
Dodatkowe zasoby
- Współdziałanie języka JavaScript "[JSImport]"/"[JSExport]" w zestawie webAssembly platformy .NET
- Współdziałanie javaScript JSImport/JSExport z platformą ASP.NET Core Blazor
- Dokumentacja interfejsu API
dotnet/runtime
W repozytorium GitHub:- Korzystanie z platformy .NET z dowolnej aplikacji JavaScript na platformie .NET 7