# From Annotations

If you already have a data-transfer class decorated with `[Event]` and standard `System.ComponentModel.DataAnnotations` attributes, you can derive an `EventSchema` from it automatically — no need to write a schema by hand.

## Prerequisites

Install both the annotations and schema packages:

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

## Annotating your class

Apply `[Event]` at class level and standard data-annotation attributes on properties:

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

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

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

    [Required]
    public string Currency { get; set; } = default!;

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

### Attribute mapping

| Data annotation                      | Schema constraint                         |
| ------------------------------------ | ----------------------------------------- |
| `[Required]`                         | `required: true`                          |
| `[Range(min, max)]`                  | `min` / `max` constraints                 |
| `[AllowedValues(...)]` / custom enum | `enum` constraint                         |
| Nullable reference type (`T?`)       | `nullable: true`                          |
| `[EventProperty(name)]`              | Overrides the property name in the schema |

## Deriving a schema

### Static helper

```csharp
using Hermodr;

var schema = EventSchema.FromDataType<OrderPlacedData>();
```

### Via the injectable factory (preferred in DI scenarios)

```csharp
using Hermodr;
using Microsoft.Extensions.DependencyInjection;

// Register the schema factory
builder.Services.AddSingleton<IEventSchemaFactory, EventSchemaFactory>();

public class MyService
{
    private readonly IEventSchemaFactory _schemaFactory;

    public MyService(IEventSchemaFactory schemaFactory)
    {
        _schemaFactory = schemaFactory;
    }

    public IEventSchema GetOrderSchema()
        => _schemaFactory.CreateFromType<OrderPlacedData>();
}
```

### From a `Type` reference

```csharp
var schema = EventSchema.FromDataType(typeof(OrderPlacedData));
```

## Generated schema

For the `OrderPlacedData` class above, the derived schema is equivalent to:

```csharp
EventSchema.Build("order.placed")
    .WithVersion("1.0")
    .WithDescription("Raised when a customer places an order")
    .AddProperty("OrderId",   "guid",    p => p.Required())
    .AddProperty("Amount",    "money",   p => p.Required().WithRange<decimal>(0.01m, 1_000_000m))
    .AddProperty("Currency",  "string",  p => p.Required())
    .AddProperty("Notes",     "string",  p => p.Nullable())
    .Build();
```

## Exporting the derived schema

Once you have an `IEventSchema`, you can export it in any supported format:

```csharp
// JSON
var jsonWriter = new EventSchemaJsonWriter(new JsonWriterOptions { Indented = true });
await jsonWriter.WriteToAsync(stream, schema);

// YAML (requires Hermodr.Schema.Yaml)
var yamlWriter = new EventSchemaYamlWriter();
await yamlWriter.WriteToAsync(stream, schema);

// AsyncAPI (requires Hermodr.Schema.AsyncApi)
var asyncApiWriter = new EventSchemaAsyncApiWriter(AsyncApiFormat.Yaml);
await asyncApiWriter.WriteToAsync(stream, schema);
```

## Related pages

* [Fluent Builder](/event-schema/fluent-builder.md)
* [Export as JSON](/event-schema/export-json.md)
* [Export as YAML](/event-schema/export-yaml.md)
* [Export as AsyncAPI](/event-schema/export-asyncapi.md)
* [Validation](/event-schema/validation.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/event-schema/from-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.
