メインコンテンツまでスキップ

属性の付与

WIT に対応するインターフェース定義を C# で記述し、適切な属性を与えることで、WaaS に付属する Source Generator がバインディングに便利なコードを自動生成します。

備考

wit2waas を使用する場合、自動的に属性が付与されるため、手動での属性の付与は不要です。
生成されたコードを利用する を参照してください。

インターフェースを宣言する

WIT のインターフェースやワールドに対応するバインディングを生成するには、C# で partialinterface を宣言し [ComponentInterface] 属性を付与します。

using WaaS.ComponentModel.Binding;

[ComponentInterface(@"env")]
public partial interface IEnv
{
/* インターフェースのメンバをここに定義 */
}

この interface に含まれる型や関数については、この interface のメンバとして定義します。定義するメンバの種類によって、それぞれ対応する属性を付与する必要があります。

関数を宣言する

インターフェースに含まれる関数を定義するには、インターフェースのメンバとしてメソッドを定義し、[ComponentApi] 属性を付与します。

using WaaS.ComponentModel.Binding;
using System.Threading.Tasks;

[ComponentInterface(@"env")]
public partial interface IEnv
{
[ComponentApi(@"show-message")]
ValueTask ShowMessage(string @message);
}
  • [ComponentApi] の引数には、WIT の関数名を指定する必要があります。
  • 戻り値の型は ValueTask 等の awaitable な型にすることができます。
    • 呼び出し元で await され、結果が取得されます。
  • そのほか、引数や戻り値に使用できる型は 関数等で使用できる型 を参照してください。
警告

awaitable な関数を呼び出す場合、ExecutionContext.Invoke() は使用できません。
ExecutionContext.InvokeAsync() を使用してください。

関数等で使用できる型

Component Model の型C# の型
stringstring
boolbool
s8sbyte
u8byte
s16short
u16ushort
s32int
u32uint
s64long
u64ulong
f32float
f64double
charWaaS.ComponentModel.Binding.ComponentChar1
recordレコードを定義する
variantバリアントを定義する
list<T>System.ReadOnlyMemory<T>
tuple<...>System.ValueTuple<...> または System.Tuple<...>
flagsフラグを定義する
enum列挙型を定義する
option<T>オプション型を使う
result<T, E>WaaS.ComponentModel.Binding.Result<TOk, TError>
own<T>リソース型を定義する
borrow<T>リソース型を定義する

レコードを定義する

Component Model の record 型は、次のように表現します。

using WaaS.ComponentModel.Binding;

[ComponentInterface(@"env")]
public partial interface IEnv
{
[ComponentRecord]
public readonly partial struct Message
{
[ComponentField]
public (string, Sprite?) Speaker { get; private init; }
[ComponentField]
public string Text { get; private init; }
[ComponentField]
public MessageAttributes Attributes { get; private init; }
}
}
  • [ComponentInterface]を付与した interface のメンバとして partialclass または struct を定義し、 [ComponentRecord] 属性を付与します。
  • プロパティには [ComponentField] 属性を付与します。
  • プロパティには init または set アクセサを付与します。アクセシビリティは問いません。
  • プロパティの型は、Component Model の型に対応する C# の型を使用します。使用できる型は 関数等で使用できる型 と同じです。

バリアントを定義する

Component Model の variant 型は、次のように表現します。

#enable nullable
using WaaS.ComponentModel.Binding;

[ComponentInterface(@"env")]
public partial interface IEnv
{
[ComponentVariant]
public readonly partial struct Sprite
{
[ComponentCase]
public MyGame.MySequencer.IEnv.WellKnownSprites? WellKnown { get; private init; }
[ComponentCase]
public string? Addressable { get; private init; }
}
}
  • [ComponentInterface]を付与した interface のメンバとして partialclass または struct を定義し、 [ComponentVariant] 属性を付与します。
  • プロパティには [ComponentCase] 属性を付与します。
  • プロパティには init または set アクセサを付与します。アクセシビリティは問いません。
  • プロパティの型は、Component Model の型に対応する C# の型を使用します。使用できる型は 関数等で使用できる型 と同じです。
    • 加えて、プロパティの型は nullable にすることを推奨します。

生成されるメンバ

バリアントの情報にアクセスするためのメンバが生成されます。

// <auto-generated />
partial interface IEnv
{
partial struct Sprite
{
public VariantCase Case { get; private init; }

public enum VariantCase
{
WellKnown,
Addressable,
}
}
}

Case プロパティを使用すると、バリアントの種類を取得できます。

return sprite.Case switch
{
IEnv.Sprite.VariantCase.WellKnown => GetWellKnownSprite(sprite.WellKnown),
IEnv.Sprite.VariantCase.Addressable => GetAddressableSprite(sprite.Addressable),
_ => throw new IndexOutOfRangeException()
};

フラグを定義する

Component Model の flags 型は、次のように表現します。

using WaaS.ComponentModel.Binding;
using System;

[ComponentInterface(@"env")]
public partial interface IEnv
{
[Flags]
public enum MessageAttributes : byte
{
Fast = 1 << 0,
Large = 1 << 1,
Slow = 1 << 2,
Auto = 1 << 3,
}
}
  • [ComponentInterface]を付与した interface のメンバとして enum を定義し、 System.Flags 属性を付与します。
  • フラグの数に応じて、byte から uint までの整数型を underlying type として使用します。
    • フラグが 8 個以下の場合は byte を使用します。
    • フラグが 16 個以下の場合は ushort を使用します。
    • そのほかの場合は uint を使用します。
備考

Component Model では、flags の持つフラグ型は32個までとなっています。

列挙型を定義する

Component Model の enum 型は、次のように表現します。

using WaaS.ComponentModel.Binding;
using System;

[ComponentInterface(@"env")]
public partial interface IEnv
{
public enum WellKnownSprites
{
Unknown,
Hero,
Rival,
Professor,
}
}
  • [ComponentInterface]を付与した interface のメンバとして enum を定義します。
  • System.Flags 属性は付与できません。
警告

Component Model の enum では、列挙定数の値を明示できません。
C# 側で列挙定数の値を明示した場合、それらは符号のない整数表現として昇順に並び替えられ、順番にインデックスが与えられます。

public enum WellKnownSprites : uint
{
Unknown = 100, // '1' in Component Model
Hero = 200, // '2' in Component Model
Rival = 0, // '0' in Component Model
Professor = 1000, // '3' in Component Model
}

オプション型を使う

Component Model の option<T> 型を表現するには、WaaS.ComponentModel.Binding.Option<T> を使用します。

ただし、次のいずれかの場合は T? も使用できます。

  • T が値型である場合
  • レコードまたはバリアントのメンバの型として直接利用されている場合
    • タプルやリストの要素など、型引数として使用される場合を除く

リソース型を定義する

[ComponentInterface] 属性を付与したインターフェースでリソース型が定義されている場合、C# 側のインターフェースには次のようなメンバが必要です。

using WaaS.ComponentModel.Binding;
using WaaS.ComponentModel.Runtime;
using System;

[ComponentInterface(@"env")]
public partial interface IEnv
{
[ComponentResource(@"some-resource-name")]
public partial interface ISomeResourceImpl : IResourceImpl
{
/* ... */
}
}

  • [ComponentInterface] を付与したインターフェースのメンバとして、[ComponentResource] 属性を付与した partial なインターフェースを定義します。
  • インターフェースは、IResourceImpl を継承します。

引数や戻り値でリソース型を使用する場合は Owned<ISomeResourceImpl> 、借用する場合は Borrowed<ISomeResourceImpl> を使用します。

引数として Owned<ISomeResourceImpl> が C# コードに渡される場合、所有権を適切にハンドルしなければなりません。

リソース型のメンバを定義する

public partial interface ISomeResourceImpl : IResourceImpl
{
[ComponentApi("[constructor]some-resource-name")]
ValueTask<Owned<ISomeResourceImpl>> SomeResource(/* ... */);

[ComponentApi("[method]some-resource-name.some-method")]
ValueTask</* return type */> SomeMethod(Borrowed<ISomeResourceImpl> self, /* ... */);

[ComponentApi("[static]some-resource-name.some-static-method")]
ValueTask</* return type */> SomeStaticMethod(/* ... */);
}
  • リソース型のインターフェースには、[ComponentApi] 属性を付与したメンバメソッドを定義します。基本的なルールは通常と同じですが、次の点で異なります。
    • [ComponentApi] の引数に、次のような名前を指定します。
      • コンストラクタ: [constructor]リソース名
      • メソッド: [method]リソース名.メソッド名
      • 静的メソッド: [static]リソース名.メソッド名
    • コンストラクタでは Owned<リソース実装型> またはそれを結果とする awaitable な型を戻り値の型とします。
    • インスタンスメソッドの場合は、一つ目の引数に Borrowed<リソース実装型> を指定します。
    • 詳細は WIT の仕様 を参照してください。

Footnotes

  1. Component Modelの文字型は Unicode Scalar Value であり、C#の char は使用できません。