# Event Annotations

The `Hermodr.Annotations` package provides attributes that let you embed event metadata directly on your data-transfer classes, removing the need to hard-code event types or versions at the call site.

## Installation

```bash
dotnet add package Hermodr.Annotations
```

## `[Event]` attribute

Applied at class level. Describes the event type, version, and other envelope defaults.

```csharp
using Hermodr;

[Event("order.placed", "1.0")]
public class OrderPlacedData
{
    public Guid OrderId { get; set; }
    public decimal Amount { get; set; }
    public string Currency { get; set; } = default!;
}
```

### Constructor overloads

| Signature                                                     | When to use                                  |
| ------------------------------------------------------------- | -------------------------------------------- |
| `[Event("type", "version")]`                                  | Most common — event type + semver string     |
| `[Event("type", "https://schemas.example.com/order.placed")]` | Event type + absolute URI to the JSON Schema |

### Properties

| Property      | Type      | Description                                                                                                                                                                                                                            |
| ------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `EventType`   | `string`  | Required. The `type` attribute of the CloudEvent.                                                                                                                                                                                      |
| `DataVersion` | `string?` | SemVer version string (set when the second argument is not a URI).                                                                                                                                                                     |
| `DataSchema`  | `Uri?`    | Absolute URI to the schema (set when the second argument is a URI).                                                                                                                                                                    |
| `Description` | `string?` | Human-readable description for documentation purposes.                                                                                                                                                                                 |
| `ContentType` | `string?` | MIME content type of the data payload (e.g. `"application/json"`). When not set, publishing uses `EventPublisherOptions.DefaultContentType` (default: `"application/cloudevents+json"`), and schema generation defaults to `"object"`. |

## `[EventProperty]` attribute

Applied at property or field level. Marks a member as part of the event payload and optionally overrides its serialised name.

```csharp
[Event("order.placed", "1.0")]
public class OrderPlacedData
{
    [EventProperty("order_id")]
    public Guid OrderId { get; set; }

    [EventProperty("amount")]
    public decimal Amount { get; set; }
}
```

### Properties

| Property      | Type      | Description                                                 |
| ------------- | --------- | ----------------------------------------------------------- |
| `Name`        | `string?` | Overrides the property name used in the serialised payload. |
| `Description` | `string?` | Human-readable description.                                 |
| `Version`     | `string?` | The event version this property belongs to.                 |
| `Schema`      | `Uri?`    | URI of the schema for this property's data.                 |

## `[EventAttributes]` attribute

A base class for attributes that inject arbitrary CloudEvent extension attributes into the envelope. This is the foundation for things like `[AmqpExchange]` and `[AmqpRoutingKey]` (see [AMQP Annotations](/project/amqp.md)).

```csharp
// Inject a custom CloudEvent extension attribute
[EventAttributes("x-tenant-id", "acme")]
[Event("order.placed", "1.0")]
public class OrderPlacedData { /* ... */ }
```

## Publishing from an annotated class

```csharp
var data = new OrderPlacedData
{
    OrderId  = Guid.NewGuid(),
    Amount   = 99.95m,
    Currency = "USD"
};

// The IEventFactory service reads [Event] and builds the CloudEvent automatically.
await publisher.PublishAsync(data);
```

## Combining with Data Annotations

Standard `System.ComponentModel.DataAnnotations` attributes (e.g. `[Required]`, `[Range]`) placed on the same class are recognised by the Schema package when generating event schemas:

```csharp
using System.ComponentModel.DataAnnotations;
using Hermodr;

[Event("order.placed", "1.0", Description = "Raised when a customer places an order")]
public class OrderPlacedData
{
    [Required]
    [EventProperty("order_id")]
    public Guid OrderId { get; set; }

    [Required]
    [Range(0.01, 1_000_000.0)]
    [EventProperty("amount")]
    public decimal Amount { get; set; }

    [Required]
    [EventProperty("currency")]
    public string Currency { get; set; } = default!;

    public string? Notes { get; set; }
}
```

→ See [Schema from Annotations](/event-schema/from-annotations.md) for how to derive a schema from this class.

## Related pages

* [Event Publisher](/core-concepts/event-publisher.md)
* [RabbitMQ Channel — AMQP Annotations](/publisher-channels/rabbitmq.md#amqp-annotations)
* [Schema from Annotations](/event-schema/from-annotations.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hermodr.deveel.org/core-concepts/event-annotations.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
