﻿# Immutable Messages samples


## Code walk-through

This sample shows how to define and exchange immutable messages between endpoints. Immutable messages can be defined as interfaces that contain only getters:

<!-- snippet: immutable-messages-as-interface -->

```cs
public interface IMyMessage
{
    string Data { get; }
}
```

<!-- endsnippet -->

Or as classes with only getters and a non-default parameterless constructor:

<!-- snippet: immutable-messages-as-class -->

```cs
public class MyMessage
{
    public MyMessage(string data)
    {
        Data = data;
    }

    public string Data { get; private set; }
}
```

<!-- endsnippet -->

### Sending messages

The sender endpoint can send messages to the receiver using either an immutable message defined as a class or one defined as an interface. In the latter case, the sender endpoint defines an internal message class that implements the public, shared interface:

<!-- snippet: immutable-messages-as-interface-implementation -->

```cs
class MyMessageImpl : IMyMessage
{
    public string Data { get; set; }
}
```

<!-- endsnippet -->

The internal class is then used by the sender endpoint at dispatch time:

<!-- snippet: immutable-messages-as-interface-sending -->

```cs
var myMessage = new MyMessageImpl()
{
    Data = data
};
return messageSession.Send(myMessage);
```

<!-- endsnippet -->

> [!NOTE]
> The class is compatible with any serializer that has public getters and setters.

### Receiving messages

To receive an immutable message defined using one of the two presented techniques, no special configuration is needed. The only requirement is a serializer capable of deserializing objects using private setters and/or non-public parameterless constructors. The receiver endpoint defines regular message handlers:

<!-- snippet: immutable-messages-as-interface-handling -->

```cs
public class MyMessageAsInterfaceHandler(ILogger<MyMessageAsInterfaceHandler> logger) :
    IHandleMessages<IMyMessage>
{
    public Task Handle(IMyMessage message, IMessageHandlerContext context)
    {
        logger.LogInformation("IMyMessage (as interface) received from server with data: {Data}", message.Data);
        return Task.CompletedTask;
    }
}
```

<!-- endsnippet -->

<!-- snippet: immutable-messages-as-class-handling -->

```cs
public class MyMessageAsClassHandler(ILogger<MyMessageAsClassHandler> logger) :
    IHandleMessages<MyMessage>
{
    public Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        logger.LogInformation("MyMessage (as class) received from server with data: {Data}", message.Data);
        return Task.CompletedTask;
    }
}
```

<!-- endsnippet -->
