Aracılığıyla paylaş


JavaScript [JSImport]/[JSExport] birlikte çalışma

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

Uyarı

ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

Bu makalede birlikte çalışma kullanarak[JSExport]/[JSImport]JS JavaScript'ten (JS) .NET çalıştırma işlemi açıklanır.

Ek yönergeler için .NET Çalışma Zamanı (dotnet/runtime) GitHub deposunda .NET WebAssembly uygulamalarını yapılandırma ve barındırma kılavuzuna bakın.

Mevcut JS uygulamalar, veya 'den JS .NET kitaplıklarını yeniden kullanmak ve yeni derlemek için genişletilmiş istemci tarafı WebAssembly desteğini kullanabilir. NET tabanlı uygulamalar ve çerçeveler.

Not

Bu makale, üzerinde herhangi bir bağımlılık olmadan uygulamalardan JS .NET çalıştırmaya Blazorodaklanır. Uygulamalarda birlikte çalışma Blazor WebAssembly kullanma [JSImport]/[JSExport] yönergeleri için bkz. JavaScript JSImport/JSExport birlikte çalışma ASP.NET Core Blazorile dışarı aktarma.

Bu yaklaşımlar yalnızca WebAssembly (WASM) üzerinde çalıştırmayı beklediğiniz durumlarda uygundur. Kitaplıklar, çağrısı OperatingSystem.IsBrowseryaparak uygulamanın üzerinde WASM çalışıp çalışmadığını belirlemek için bir çalışma zamanı denetimi yapabilir.

Önkoşullar

.NET SDK (en son sürüm)

wasm-tools İş yükünü, ilgili MSBuild hedeflerini getiren bir yönetim komut kabuğuna yükleyin:

dotnet workload install wasm-tools

Araçlar, Visual Studio yükleyicisindeki ASP.NET ve web geliştirme iş yükü altında Visual Studio yükleyicisi aracılığıyla da yüklenebilir. İsteğe bağlı bileşenler listesinden .NET WebAssembly derleme araçları seçeneğini belirleyin.

İsteğe bağlı olarak, bir tarayıcı uygulamasında (WebAssembly Browser App) veya bir Node'da WebAssembly'de .NET kullanmaya başlamak için deneysel proje şablonları içeren iş yükünü yükleyin wasm-experimental .jstabanlı konsol uygulaması (WebAssembly Konsol Uygulaması). Birlikte çalışma ile mevcut bir uygulamayı tümleştirmeyi JS[JSExport][JSImport]/planlıyorsanız bu iş yükü gerekli değildir.JS

dotnet workload install wasm-experimental

Şablonlar nuget paketinden Microsoft.NET.Runtime.WebAssembly.Templates aşağıdaki komutla da yüklenebilir:

dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates

Daha fazla bilgi için Deneysel iş yükü ve proje şablonları bölümüne bakın.

Ad Alanı

JS Bu makalede açıklanan birlikte çalışma API'si, ad alanı içindeki System.Runtime.InteropServices.JavaScript öznitelikler tarafından denetlenmektedir.

Proje yapılandırması

Birlikte çalışma özelliğini etkinleştirmek JS üzere bir projeyi (.csproj) yapılandırmak için:

  • Hedef çerçeve takma adını ({TARGET FRAMEWORK} yer tutucu) ayarlayın:

    <TargetFramework>{TARGET FRAMEWORK}</TargetFramework>
    

    .NET 7 (net7.0) veya üzeri desteklenir.

  • AllowUnsafeBlocks Roslyn derleyicisindeki kod oluşturucunun birlikte çalışma için JS işaretçileri kullanmasına izin veren özelliğini etkinleştirin:

    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    

    Uyarı

    Birlikte çalışma API'sinin JS etkinleştirilmesi AllowUnsafeBlocksgerekir. Güvenlik ve kararlılık risklerine neden olabilecek .NET uygulamalarında kendi güvenli olmayan kodunuzu uygularken dikkatli olun. Daha fazla bilgi için bkz . Güvenli olmayan kod, işaretçi türleri ve işlev işaretçileri.

Aşağıda, yapılandırmadan sonra örnek bir proje dosyası (.csproj) verilmiştir. Yer {TARGET FRAMEWORK} tutucu hedef çerçevedir:

<Project Sdk="Microsoft.NET.Sdk.WebAssembly">

  <PropertyGroup>
    <TargetFramework>{TARGET FRAMEWORK}</TargetFramework>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>

</Project>
  • Hedef çerçeve adını ayarlayın:

    <TargetFramework>net7.0</TargetFramework>
    

    .NET 7 (net7.0) veya üzeri desteklenir.

  • Çalışma zamanı tanımlayıcısı için belirtin browser-wasm :

    <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
    
  • Yürütülebilir bir çıkış türü belirtin:

    <OutputType>Exe</OutputType>
    
  • AllowUnsafeBlocks Roslyn derleyicisindeki kod oluşturucunun birlikte çalışma için JS işaretçileri kullanmasına izin veren özelliğini etkinleştirin:

    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    

    Uyarı

    Birlikte çalışma API'sinin JS etkinleştirilmesi AllowUnsafeBlocksgerekir. Güvenlik ve kararlılık risklerine neden olabilecek .NET uygulamalarında kendi güvenli olmayan kodunuzu uygularken dikkatli olun. Daha fazla bilgi için bkz . Güvenli olmayan kod, işaretçi türleri ve işlev işaretçileri.

  • Disk üzerindeki bir dosyaya işaret etmek için belirtin WasmMainJSPath . Bu dosya uygulamayla yayımlanır, ancak .NET'i mevcut JS bir uygulamayla tümleştirirseniz dosyanın kullanılması gerekmez.

    Aşağıdaki örnekte, diskteki JS dosya şeklindedir main.js, ancak herhangi bir JS dosya adı izin verilebilir:

    <WasmMainJSPath>main.js</WasmMainJSPath>
    

Yapılandırmadan sonra örnek proje dosyası (.csproj):

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

JavaScript birlikte çalışma açık WASM

Aşağıdaki örnekteki API'ler kaynağından dotnet.jsiçeri aktarılır. Bu API'ler, C# kodunuz içine aktarabileceğiniz adlandırılmış modüller ayarlamanıza ve dahil olmak üzere Program.Main.NET kodunuz tarafından kullanıma sunulan yöntemlere çağrı yapmanızı sağlar.

Önemli

Bu makalenin genelindeki "İçeri aktarma" ve "dışarı aktarma" işlemleri .NET perspektifinden tanımlanır:

  • Bir uygulama yöntemleri içeri aktararak JS .NET'ten çağrılabilmelerini sağlar.
  • Uygulama, .NET yöntemlerini dışarı aktararak uygulamasından JSçağrılabilmelerini sağlar.

Aşağıdaki örnekte:

  • Dosya dotnet.js , .NET WebAssembly çalışma zamanını oluşturmak ve başlatmak için kullanılır. dotnet.js , uygulamanın derleme çıkışının bir parçası olarak oluşturulur.

    Önemli

    Mevcut bir uygulamayla tümleştirmek için yayımlama çıktı klasörünün içeriğini kopyalayın† uygulamanın dağıtım varlıklarına kopyalayın; böylece uygulamanın içeriğiyle birlikte rest sunulabilmesini sağlayın. Üretim dağıtımları için, komut kabuğunda komutuyla dotnet publish -c Release uygulamayı yayımlayın ve çıkış klasörünün içeriğini uygulamayla dağıtın.

    † Yayımlama çıktı klasörü, yayımlama profilinizin hedef konumudur. .NET 8 veya sonraki sürümlerde bir Release profil için varsayılan değer, bin/Release/{TARGET FRAMEWORK}/publishyer tutucunun {TARGET FRAMEWORK} hedef çerçeve olduğu yer tutucudur (örneğin, net8.0).

  • dotnet.create() .NET WebAssembly çalışma zamanını ayarlar.

  • setModuleImports bir adı .NET'e içeri aktarma işlevleri modülüyle JS ilişkilendirir. Modül JS , kullanıcı arabiriminde geçerli kronometre saatini görüntüleme süresini ve öğe seçicisini kabul eden bir dom.setInnerText işlev içerir. Modülün adı herhangi bir dize olabilir (dosya adı olması gerekmez), ancak ile kullanılan adla eşleşmelidir (bu makalenin JSImportAttribute ilerleyen bölümlerinde açıklanmıştır). dom.setInnerText işlevi C# içine aktarılır ve C# yöntemi tarafından çağrılırSetInnerText. SetInnerText yöntemi bu bölümün ilerleyen bölümlerinde gösterilir.

  • exports.StopwatchSample.Reset()'den JS.NET'e (StopwatchSample.Reset) çağrılar. Reset C# yöntemi çalışıyorsa kronometreyi yeniden başlatır veya çalışmıyorsa sıfırlar. Reset yöntemi bu bölümün ilerleyen bölümlerinde gösterilir.

  • exports.StopwatchSample.Toggle()'den JS.NET'e (StopwatchSample.Toggle) çağrılar. Toggle C# yöntemi, şu anda çalışıp çalışmadığı durumuna bağlı olarak kronometreyi başlatır veya durdurur. Toggle yöntemi bu bölümün ilerleyen bölümlerinde gösterilir.

  • runMain() çalıştırır Program.Main.

  • setModuleImports bir adı .NET'e içeri aktarma işlevleri modülüyle JS ilişkilendirir. Modül JS , geçerli sayfa adresini (URL) döndüren bir window.location.href işlev içerir. Modülün adı herhangi bir dize olabilir (dosya adı olması gerekmez), ancak ile kullanılan adla eşleşmelidir (bu makalenin JSImportAttribute ilerleyen bölümlerinde açıklanmıştır). window.location.href işlevi C# içine aktarılır ve C# yöntemi tarafından çağrılırGetHRef. GetHRef yöntemi bu bölümün ilerleyen bölümlerinde gösterilir.

  • exports.MyClass.Greeting()'den JS.NET'e (MyClass.Greeting) çağrılar. Greeting C# yöntemi, işlevi çağırmanın window.location.href sonucunu içeren bir dize döndürür. Greeting yöntemi bu bölümün ilerleyen bölümlerinde gösterilir.

  • dotnet.run() çalıştırır Program.Main.

JS modül:

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();

C# dilinden çağrılabilmesi için bir JS işlevi içeri aktarmak için eşleşen yöntem imzasının yenisini JSImportAttribute kullanın. için ilk parametre JSImportAttribute , içeri aktaracak işlevin JS adı, ikinci parametre ise modülün adıdır.

Aşağıdaki örnekte, dom.setInnerText yöntem çağrıldığında SetInnerText işlev modülden main.js çağrılır:

[JSImport("dom.setInnerText", "main.js")]
internal static partial void SetInnerText(string selector, string content);

Aşağıdaki örnekte, window.location.href yöntem çağrıldığında GetHRef işlev modülden main.js çağrılır:

[JSImport("window.location.href", "main.js")]
internal static partial string GetHRef();

İçeri aktarılan yöntem imzasında, çalışma zamanı tarafından otomatik olarak hazırlanmış parametreler ve dönüş değerleri için .NET türlerini kullanabilirsiniz. İçeri aktarılan yöntem parametrelerinin nasıl düzenlendiğini denetlemek için kullanın JSMarshalAsAttribute<T> . Örneğin, veya olarak System.Runtime.InteropServices.JavaScript.JSType.Number System.Runtime.InteropServices.JavaScript.JSType.BigIntsıralamayı long seçebilirsiniz. Geri çağırmaları, çağrılabilen işlevler olarak sıralanmış parametreler olarak geçirebilirsinizActionFunc<TResult>/.JS Hem hem de JS yönetilen nesne başvurularını geçirebilirsiniz ve bunlar proxy nesneleri olarak sıralanır ve ara sunucu çöp toplanana kadar nesneyi sınır boyunca canlı tutar. Ayrıca, bir sonuçla Task zaman uyumsuz yöntemleri içeri ve dışarı aktarabilirsiniz. Bu yöntemler, promise olarak JSsıralanır. Sıralanmış türlerin çoğu, hem içeri hem de dışarı aktarılan yöntemler üzerinde parametre olarak ve dönüş değerleri olarak her iki yönde de çalışır.

Genel ad alanında erişilebilen işlevler, işlev adında önek globalThis kullanılarak ve modül adı sağlanmadan [JSImport] özniteliği kullanılarak içeri aktarılabilir. Aşağıdaki örnekte ön console.log ek olarak verilmiştir globalThis. İçeri aktarılan işlev C# yöntemi tarafından çağrılır ve C# Log dize iletisini (message) kabul eder ve C# dizesini için console.logolarak JSString derler:

[JSImport("globalThis.console.log")]
internal static partial void Log([JSMarshalAs<JSType.String>] string message);

.NET yöntemini içinden JSçağrılabilecek şekilde dışarı aktarmak için kullanın JSExportAttribute.

Aşağıdaki örnekte, her yöntem öğesine JS dışarı aktarılır ve işlevlerden JS çağrılabilir:

  • Toggle yöntemi, çalışma durumuna bağlı olarak kronometreyi başlatır veya durdurur.
  • Reset yöntemi çalışıyorsa kronometreyi yeniden başlatır veya çalışmıyorsa sıfırlar.
  • IsRunning yöntemi kronometrenin çalışıp çalışmadığını gösterir.
[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;

Aşağıdaki örnekte yöntemi, Greeting yöntemini çağırmanın GetHRef sonucunu içeren bir dize döndürür. Daha önce gösterildiği gibi C GetHref # yöntemi JS modülden işlevi için window.location.href çağrısında bulunur main.js . window.location.href geçerli sayfa adresini (URL) döndürür:

[JSExport]
internal static string Greeting()
{
    var text = $"Hello, World! Greetings from {GetHRef()}";
    Console.WriteLine(text);
    return text;
}

Deneysel iş yükü ve proje şablonları

Birlikte çalışma işlevini göstermek JS ve birlikte çalışma proje şablonlarını almak JS için iş yükünü yükleyin wasm-experimental :

dotnet workload install wasm-experimental

İş wasm-experimental yükü iki proje şablonu içerir: wasmbrowser ve wasmconsole. Bu şablonlar şu anda deneyseldir ve bu da şablonlar için geliştirici iş akışının geliştiği anlamına gelir. Ancak, şablonlarda kullanılan .NET ve JS API'ler .NET 8'de desteklenir ve üzerinde WASM JS.NET kullanmak için bir temel sağlar.

Şablonlar nuget paketinden Microsoft.NET.Runtime.WebAssembly.Templates aşağıdaki komutla da yüklenebilir:

dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates

Tarayıcı uygulaması

Komut satırından wasmbrowser şablonla bir tarayıcı uygulaması oluşturabilirsiniz. Bu, .NET'i ve JS tarayıcıda birlikte kullanmayı gösteren bir web uygulaması oluşturur:

dotnet new wasmbrowser

Alternatif olarak Visual Studio'da proje şablonunu kullanarak WebAssembly Browser App uygulamayı oluşturabilirsiniz.

Uygulamayı Visual Studio'dan veya .NET CLI kullanarak oluşturun:

dotnet build

Visual Studio'dan veya .NET CLI kullanarak uygulamayı derleyip çalıştırın:

dotnet run

Alternatif olarak şu komutu yükleyin ve kullanındotnet serve:

dotnet serve -d:bin/$(Configuration)/{TARGET FRAMEWORK}/publish

Yukarıdaki örnekte yer tutucu hedef {TARGET FRAMEWORK} çerçeve adıdır.

Düğüm.js konsol uygulaması

Altında Düğümjs olarak çalışan WASM bir uygulama oluşturan şablonla wasmconsole bir konsol uygulaması veya V8 konsol uygulaması oluşturabilirsiniz:

dotnet new wasmconsole

Alternatif olarak Visual Studio'da proje şablonunu kullanarak WebAssembly Console App uygulamayı oluşturabilirsiniz.

Uygulamayı Visual Studio'dan veya .NET CLI kullanarak oluşturun:

dotnet build

Visual Studio'dan veya .NET CLI kullanarak uygulamayı derleyip çalıştırın:

dotnet run

Alternatif olarak, dosyayı içeren main.mjs yayımlama çıktı dizininden herhangi bir statik dosya sunucusunu başlatın:

node bin/$(Configuration)/{TARGET FRAMEWORK}/{PATH}/main.mjs

Yukarıdaki örnekte, {TARGET FRAMEWORK} yer tutucu hedef çerçeve takma adıdır ve {PATH} yer tutucu dosyanın yoludurmain.mjs.

Ek kaynaklar