RequiredMethod for MapperFor Attribute - lobodava/artisan-orm GitHub Wiki

MappingManager discovers mapper methods by the names CreateObject, CreateObjectRow, CreateDataTable, and CreateDataRow. A mapper need not implement all four: a read-only entity can provide only CreateObject.

MapperFor accepts a params RequiredMethod[] argument. Its values declare which methods must be present; combining values takes their union. They do not disable discovery of other methods. This is an ordinary enum, not a flags enum: combine requirements with comma-separated arguments, not bitwise |.

Value Required methods
All CreateObject, CreateObjectRow, CreateDataTable, CreateDataRow
AllMain CreateObject, CreateDataTable, CreateDataRow
BothForObject CreateObject, CreateObjectRow
BothForDataTable CreateDataTable, CreateDataRow
CreateObject CreateObject
CreateObjectRow CreateObjectRow

For example, a mapper for an entity that is only read can declare:

[MapperFor(typeof(RecordType), RequiredMethod.CreateObject)]
public static class RecordTypeMapper
{
    // Assumes the SELECT returns one non-null int column named Id.
    public static RecordType CreateObject(Microsoft.Data.SqlClient.SqlDataReader reader) =>
        new RecordType { Id = reader.GetInt32(0) };
}

This example assumes an application RecordType class with an int Id property. The corresponding read/write mapper can use [MapperFor(typeof(User), RequiredMethod.AllMain)], equivalent to requesting CreateObject together with BothForDataTable. A TVP-only mapper can request BothForDataTable.

Omitting the requirement argument imposes no method-presence requirement by itself. An operation still needs its function: an entity ReadTo<User>() needs CreateObject, mapper-based AddTableParam needs both DataTable methods, and ReadToObjectRow<User>() needs CreateObjectRow. Supply the functions used by the application instead of adding empty stubs.

A self-check of the mapper's intended capabilities

Partial mappers are valid, so a missing method is not automatically a mistake. RequiredMethod makes the author's intention explicit: for example, AllMain promises both entity reads and conversion to table data. The contract catches an accidentally omitted, deleted, or renamed method even when no current call needs it. Omitting the second argument removes that declared presence requirement; it does not turn off signature validation or the requirements of actual operations.

The runtime checks this promise during mapper discovery; the Roslyn analyzer checks it earlier, in the editor and during the build. Neither check proves that a method body maps the data correctly. See compile-time mapper validation (Roslyn) for the reasoning, examples, and the distinction between ART002 and ART006.

Runtime and build-time validation

At runtime, a missing method required by the attribute causes ArtisanMappingException during lazy mapper discovery. Conventional signatures are public, static, non-generic methods as shown in Mappers. Reflection lookup and delegate compatibility determine which methods can be used; overloaded or incompatible methods can also fail validation.

The current repository's unreleased analyzer also checks the contract at build time and during live document analysis. It reports errors ART001–ART007 for missing mappings/functions, incompatible signatures, duplicate or ambiguous mappings, and invalid registrations. This is additional validation; the runtime checks remain. Check the installed package for analyzer availability rather than assuming every older release contains it.

The current unreleased fix makes AllMain enforce all three methods listed above at runtime as well as in analyzer checks. Older code enforced only CreateObject for that value. A read-only mapper should therefore declare CreateObject, rather than AllMain.

The analyzer does not inspect a live database or prove that reader ordinals, SQL types, and nullability match. For full diagnostics and compatibility details, see compile-time mapper validation (Roslyn) and 4.1.0 changes.

⚠️ **GitHub.com Fallback** ⚠️