C# API reference
The NativeChannels APIs below describe the current source tree. This is a focused reference for application and plugin authors, with links to the implementation and detailed guides. Native adapter APIs are covered in the Android, Apple, and Windows guides.
Channel service
Inject IChannelService after calling UseNativeChannels. Each channel factory returns an independently disposable handle. The DI container owns the service.
namespace NativeChannels;
public interface IChannelService : IAsyncDisposable
{
MethodChannel GetMethodChannel(string name, MethodChannelOptions? options = null);
BasicMessageChannel GetBasicMessageChannel(string name, BasicMessageChannelOptions? options = null);
EventChannel GetEventChannel(string name, EventChannelOptions? options = null);
}using var channel = channels.GetMethodChannel("sample");
string? result = await channel.InvokeAsync<string>("echo", "Hello");See MethodChannel for both call directions and lifecycle for ownership.
MethodChannel
| Member | Behavior |
|---|---|
Name | The named endpoint shared by compatible handles. |
InvokeAsync(method, arguments, cancellationToken, options) | Awaits completion without returning the result value. |
InvokeAsync<T>(method, arguments, cancellationToken, options) | Converts the reply using the configured serializer; returns Task<T?>. |
SetMethodCallHandler(handler) | Registers one incoming async handler and returns its ownership token. |
RemoveMethodCallHandler() | Removes this handle's incoming registration. |
Dispose() / DisposeAsync() | Ends this handle's operations and removes its registrations. |
The handler signature is Func<MethodCall, CancellationToken, ValueTask<object?>>. Return the result value, including a successful null, or throw a structured ChannelException. Retain the registration token for as long as native code may invoke the handler.
BasicMessageChannel
| Member | Behavior |
|---|---|
SendAsync(message, cancellationToken, options) | Sends a value and returns the decoded reply. |
SendAsync<T>(message, cancellationToken, options) | Converts the reply with the configured serializer. |
SetMessageHandler(handler) | Registers one asynchronous value/reply handler and returns its ownership token. |
RemoveMessageHandler() | Removes this handle's incoming registration. |
Dispose() / DisposeAsync() | Cancels this handle's requests and removes its handler. |
See basic messages for codecs, dispatch, and native helpers.
EventChannel
| Member | Behavior |
|---|---|
ListenAsync<T>(arguments, cancellationToken) | Returns an async sequence; each enumeration starts an independent subscription. |
SetStreamHandler(handler) | Serves independent IAsyncEnumerable<object?> producers to remote subscribers. |
RemoveStreamHandler() | Removes this handle's stream registration and cancels its active producers. |
Dispose() / DisposeAsync() | Cancels this handle's subscriptions and removes its registration. |
EventChannelOptions controls BufferCapacity (64) and OverflowPolicy (Fail, DropOldest, DropNewest). Streams have no invocation timeout. See event streams for cleanup, terminal signals, and Kotlin/Swift producers. EventBufferOverflowException has code event_overflow.
Calls and options
MethodCall.Method identifies the operation. Arguments exposes the decoded value; GetArguments<T>() converts the entire value and GetArgument<T>(name) reads a map field.
namespace NativeChannels;
public sealed record MethodChannelOptions
{
public TimeSpan? Timeout { get; init; }
public IMethodCodec? Codec { get; init; }
public ChannelHandlerDispatcher? HandlerDispatcher { get; init; }
}
public delegate ValueTask<object?> ChannelHandlerDispatcher(
Func<ValueTask<object?>> handler,
CancellationToken cancellationToken
);
public sealed record ChannelInvocationOptions
{
public TimeSpan? Timeout { get; init; }
}
public sealed record BasicMessageChannelOptions
{
public TimeSpan? Timeout { get; init; }
public IMessageCodec? Codec { get; init; }
public ChannelHandlerDispatcher? HandlerDispatcher { get; init; }
}
public enum EventOverflowPolicy
{
Fail,
DropOldest,
DropNewest,
}
public sealed record EventChannelOptions
{
public int BufferCapacity { get; init; } = 64;
public EventOverflowPolicy OverflowPolicy { get; init; } = EventOverflowPolicy.Fail;
}A nullable timeout means inherit. Precedence is invocation → channel → service. Use Timeout.InfiniteTimeSpan explicitly to disable the timer. Zero and other negative values are rejected. See configuration for timeouts and dispatchers.
Startup and native registration
UseNativeChannels(Action<NativeChannelsOptions>?) configures one native session and its services. NativeChannelsOptions exposes Modules, ViewFactories, DefaultTimeout, Limits, and Json metadata options. Optional Diagnostics is available from 0.1.0-preview.2.
namespace NativeChannels;
/// <summary>Explicit native adapter entrypoints. AppleFramework is a bundled framework's simple name.</summary>
public sealed record NativeModuleRegistration(string AndroidClass, string AppleClass, string? AppleFramework = null)
{
#if WINDOWS
/// <summary>Creates a fresh Windows adapter for each transport. The transport owns its disposal.</summary>
public Func<IWindowsChannelModule>? WindowsFactory { get; init; }
#endif
}Use fully qualified Android class names and the explicitly exported Objective-C class name. Apple framework names omit the .framework extension. See the native guides for compiled asset packaging.
MauiChannelDispatchers.MainThread runs a managed incoming handler through MAUI's UI dispatcher. See threading for FIFO handler entry and asynchronous completion.
Diagnostics
Assign a ChannelDiagnostics instance to NativeChannelsOptions.Diagnostics, or initialize ChannelService.Diagnostics when using Core directly. Its observer receives metadata-only ChannelDiagnosticEvent records for method/message starts and completions. Diagnostics are disabled by default. See diagnostics for the fields, coverage, and callback threading contract.
Native views
| Member | Contract |
|---|---|
PlatformChannelView.FactoryName | Explicit registration name; configure before connecting. |
CreationParameters | Value encoded with the configured JSON codec once per connection. |
InstanceId / Channel | Current unique ID and MethodChannel, or null when disconnected. |
Connected / Disconnected | Connection notifications on the UI thread. Reinstall handlers on each connection. |
Reconnect() | Recreate the native instance and invalidate the old channel; requires a MAUI handler. |
DisconnectAsync() | Remove content and await bridge cleanup. |
NativeViewFactoryRegistration(Name, AndroidClass, AppleClass, AppleFramework) is added to NativeChannelsOptions.ViewFactories. UseNativeChannels installs PlatformChannelViewHandler. All view operations require the UI thread. See native views for native factory interfaces, packaging, sizing, and ownership.
Serialization and errors
| Type | Responsibility |
|---|---|
IMessageCodec / JsonMessageCodec | Encode and decode supported tagged values. |
IMethodCodec / JsonMethodCodec | Encode calls, successful results, errors, and unimplemented methods. |
ChannelSerializer | Convert typed values with configurable System.Text.Json metadata. |
ChannelLimits | Validate payload size, name length, and nesting depth. |
ChannelException | Preserve native Code, Message, Details, and Platform. |
ChannelNotFoundException | Identify a missing named endpoint. |
MethodNotImplementedException | Identify an unsupported operation on an existing endpoint. |
ChannelSerializationException | Reject malformed or unsupported values and conversions. |
ChannelTransportException | Report bridge or transport failures. |
Cancellation, timeouts, and disposed handles use standard .NET exceptions. See error handling and typed values.
Messenger and transport
| Type | Responsibility |
|---|---|
IBinaryMessenger / BinaryMessenger | Named binary requests, incoming handlers, correlation IDs, and pending-request lifetimes. |
IChannelTransport | Versioned requests, responses, cancellation, and transport disposal. |
NativeChannelTransport | Connect the messenger to Kotlin, Swift, or Windows C# adapters. |
InMemoryTransport.CreatePair() | Connect two isolated in-process endpoints; also used for portable tests. |
See binary messenger, protocol, and testing for contracts and complete portable examples.
The Windows target adds NativeModuleRegistration.WindowsFactory (Func<IWindowsChannelModule>), IWindowsChannelModule.Register(IChannelService) and module disposal. For views, NativeViewFactoryRegistration.WindowsFactory is a Func<WindowsViewContext, WindowsNativeView>. These members are available in Windows assemblies; guard shared registration code with #if WINDOWS.
Currency reference plugin
This optional example demonstrates a typed facade over MethodChannel. Its API is not part of the NativeChannels API.
namespace Plugin.Maui.Currency;
/// <summary>Looks up currency symbols using the current native display locale.</summary>
public interface ICurrencyService
{
/// <summary>Returns the native symbol for a three-letter currency code, such as USD or EUR.</summary>
/// <remarks>Input is trimmed and normalized to uppercase. A symbol can include a country prefix,
/// or be the currency code itself when the platform has no localized symbol.</remarks>
/// <exception cref="ArgumentException">The code does not contain three ASCII letters.</exception>
/// <exception cref="NativeChannels.ChannelException">The native platform does not recognize the code.</exception>
Task<string> GetSymbolAsync(string currencyCode, CancellationToken cancellationToken = default);
}Register the module with options.AddCurrency() inside the existing UseNativeChannels call, and the singleton service with builder.Services.AddCurrency(). The plugin package includes its native adapters. See the reference plugin guide to study the implementation, build its local package, and run the sample. It has not been published to NuGet.org.