rust_ef/registration.rs
1//! Compile-time entity registration via `inventory`.
2//!
3//! The `#[derive(EntityType)]` macro emits an `inventory::submit!` for each
4//! entity type, registering a type-erased [`EntityRegistration`]. The
5//! `DbContext` discovers these at runtime via
6//! `inventory::iter::<EntityRegistration>()` (see `DbContext::discover_entities`).
7//!
8//! Similarly, `#[entity(T)]` applied to `impl IEntityTypeConfiguration<T>`
9//! blocks emits an [`EntityConfigRegistration`], whose `apply_fn` is invoked by
10//! `DbContext::discover_entities()` to apply Fluent API overrides to the
11//! `ModelBuilder`.
12
13use crate::metadata::EntityTypeMeta;
14use crate::model_builder::ModelBuilder;
15use std::any::TypeId;
16
17/// Type-erased registration for an entity type.
18///
19/// Emitted automatically by `#[derive(EntityType)]`. Collected at link time
20/// via `inventory::collect!`, so every entity type compiled into the final
21/// binary is visible to `DbContext::discover_entities()`.
22#[derive(Debug)]
23pub struct EntityRegistration {
24 pub type_id: TypeId,
25 pub type_name: &'static str,
26 pub meta_fn: fn() -> EntityTypeMeta,
27 /// Which DbContext key this entity belongs to.
28 /// `None` = default context; `Some("key")` = keyed context.
29 /// Set by `#[context("key")]` on the entity struct.
30 pub context_key: Option<&'static str>,
31}
32
33impl EntityRegistration {
34 pub fn meta(&self) -> EntityTypeMeta {
35 (self.meta_fn)()
36 }
37}
38
39inventory::collect!(EntityRegistration);
40
41/// Type-erased registration for an `IEntityTypeConfiguration<T>` impl block.
42///
43/// Emitted by the `#[entity(T)]` attribute macro. The `apply_fn`
44/// instantiates the configuration via `Default::default()` and invokes
45/// `IEntityTypeConfiguration::configure(&mut EntityTypeBuilder)` on a
46/// freshly-borrowed `ModelBuilder`.
47#[derive(Clone, Copy)]
48pub struct EntityConfigRegistration {
49 pub type_id: TypeId,
50 pub type_name: &'static str,
51 pub apply_fn: fn(&mut ModelBuilder),
52 /// Which DbContext key this configuration applies to.
53 /// `None` = default context; `Some("key")` = keyed context.
54 /// Set by `#[entity(T, "key")]` attribute's optional second argument.
55 pub context_key: Option<&'static str>,
56}
57
58impl std::fmt::Debug for EntityConfigRegistration {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 f.debug_struct("EntityConfigRegistration")
61 .field("type_id", &self.type_id)
62 .field("type_name", &self.type_name)
63 .finish()
64 }
65}
66
67inventory::collect!(EntityConfigRegistration);