Namespace Serenity.ServiceExtensionCreator.Editor
Classes
AggregateCatalog
Reflection-based discovery of Serenity's extendable aggregates: every I{X}Service interface
deriving from IService, filtered to primary aggregates (see
Serenity.ServiceExtensionCreator.Editor.AggregateCatalog.HasPrimaryModuleFolder(System.String)) and enriched with the concrete Unity service/installer types,
virtualization status and InterfaceAdapters presence. The guarded assembly scan mirrors
AutoRegisterServiceBootstrap.SafeGetTypes so one broken assembly can never abort discovery.
AggregateDescriptor
Immutable snapshot of one discovered Serenity aggregate (a "{X}" whose I{X}Service interface
derives from Serenity.Global.Application.Interfaces.IService), as produced by
Discover().
AsmdefReferenceWriter
Resolves the asmdef reference sets a generated service extension's layers need, writes brand-new layered asmdefs (the code layer, Installation, and Tests each own their folder — no existing asmdef is ever mutated), and appends the PipelineReplace task to the project's initialization pipeline profile.
ClassVirtualizer
Editor helper that makes an existing class subclass-friendly by rewriting its eligible public
members to public virtual — the missing first step before the Subclass style (or the Class kind)
can target a class with no overridable members. The Unity half only locates the script, enumerates the
compiled type's patchable members, and confirms with the user; the actual text rewrite lives in the
pure VirtualizationEngine, which refuses whole-file rather than ever writing a partial
rewrite. Fields, events, indexers, operators, statics and nested types are deliberately out of scope —
only plain public and protected methods and properties are patched (protected internal and
private protected members are excluded: overriding them across assemblies carries accessibility
subtleties the tool does not model).
ExtensionPointCatalog
Reflection-based discovery of every Serenity extension point beyond the I{X}Service aggregates
AggregateCatalog already covers: persistence stores, aggregate repositories, aggregate
gateways, curated infrastructure factories, and the abstract PersistenceInstaller backend seam.
The guarded assembly scan is shared with AggregateCatalog via Serenity.ServiceExtensionCreator.Editor.AggregateCatalog.SafeGetLoadedTypes.
Every target type is resolved by simple-name string matching over the loaded-types scan rather than a
compile-time reference (mirrors Serenity.ServiceExtensionCreator.Editor.AggregateCatalog.FindType(System.Collections.Generic.List{System.Type},System.String,System.Func{System.Type,System.Boolean})), so this editor assembly never
needs an asmdef reference to Persistence, FilePersistence, Score, AudioPlayer, etc.
ExtensionPointDescriptor
Immutable snapshot of one discovered Serenity extension point, as produced by Discover(). For Service this simply wraps an AggregateDescriptor (see FromAggregate(AggregateDescriptor)) so AggregateCatalog and its tests keep working unchanged; every other kind is built directly from reflection over the matching contract type.
MemberPatch
One member the engine must mark virtual: its name, whether it anchors as a property
(no parameter list) or a method, which access token its declaration anchors on (protected when
IsProtected, public otherwise — protected internal/private protected
members are never patched), and how many same-name same-access declarations the source must contain —
the engine's whole-file safety check (see Rewrite(string, IReadOnlyList<MemberPatch>)).
NotSubclassableUserClass
One entry of DiscoverNotSubclassableUserClasses(): a public user class the tool cannot subclass, paired with the human-readable reason the picker shows on its disabled row (sealed / abstract / no public or protected instance methods).
RewriteResult
Outcome of one Rewrite(string, IReadOnlyList<MemberPatch>) call — all-or-nothing: on refusal RewrittenText is null and RefusalReason explains why nothing was changed.
ServiceExtensionCreator
Generates a service extension for a discovered AggregateCatalog aggregate: the service
class (fresh implementation, decorator, or infrastructure subclass), its DI wiring, an optional
initialization-pipeline task, layered asmdefs, a test stub and a README — in one pass, with rollback on
failure. Every generated aggregate mirrors the layout real Serenity aggregates use (see Unity/Score,
Unity/PlayerPrefsPersistence): a code layer (Application or Infrastructure) under
Services/, an Installation/ layer with Installers/ (and Settings/ for a
PipelineReplace task asset), an optional Tests/ layer, and a root README.md — each layer
owning its own folder and, unless Skip, its own asmdef. Mirrors the structure of
CutsceneCreator / ModalCreator: this class only mutates the project; a future wizard window
collects the ServiceExtensionCreator.Input.
ServiceExtensionCreator.Input
Everything needed to generate one service extension.
ServiceExtensionCreator.Result
Outcome of a Create(Input) call.
ServiceExtensionCreatorWindow
Step-by-step window for generating a service extension: pick an extension point (a service aggregate, a persistence store, an aggregate repository/gateway, a curated infrastructure factory, or the persistence installer seam), a style, a name, a target folder, wiring, and extras, then create. The window only collects input and renders results; ServiceExtensionCreator does the actual validation and generation work for every ExtensionPointKind.
ServiceExtensionReport
Result of CreateFromJson(string), mirroring ServiceExtensionCreator.Result for headless/agent consumption: what was created, what was skipped, and why it failed if it did.
ServiceExtensionRunner
Headless / JSON entry points for ServiceExtensionCreator, mirroring
SerenityThemeBuilderRunner so CI or an AI agent can generate a service extension without the
ServiceExtensionCreatorWindow wizard — either from the command line
(CreateFromCommandLine()) or, with the editor already open, by calling
CreateFromJson(string) directly (e.g. via UnityMCP reflection).
ServiceExtensionScriptGenerator
Code-gen templating for a generated service extension: the service class (per
ServiceExtensionCreator.Style), its DI wiring script, the optional replacement task
asset, a test stub and a README (mirrors EventDispatcherActionScriptGenerator's templating
approach). Every generated type reference is resolved through Serenity.ServiceExtensionCreator.Editor.ServiceExtensionScriptGenerator.FormatType(System.Type), which also
records the referenced namespace so the emitted file gets a clean using block instead of
fully-qualified names throughout — readable output a developer will immediately edit by hand.
ServiceExtensionScriptGenerator.GeneratedExtensionPointLayout
Every path CreateExtensionPointReadme(ExtensionPointDescriptor, Input, string, GeneratedExtensionPointLayout, List<string>, string) needs to describe a generated Store/Repository/Gateway/Factory/Installer layout.
ServiceExtensionScriptGenerator.GeneratedLayout
Every path CreateReadme(AggregateDescriptor, Input, string, GeneratedLayout, List<string>, string) needs to describe the generated layout, bundled so its signature does not balloon into an unreadable parameter list.
ServiceExtensionScriptGenerator.InstallerHookWiringRequest
Everything CreateInstallerHookWiringScript(InstallerHookWiringRequest, List<string>) needs to generate a Repository/Gateway wiring subclass, bundled so its signature does not balloon into an unreadable parameter list (mirrors ServiceExtensionScriptGenerator.GeneratedLayout).
ServiceExtensionScriptGenerator.PersistenceInstallerSubclassRequest
Everything CreatePersistenceInstallerSubclassScript(PersistenceInstallerSubclassRequest, List<string>) needs to generate a Store/Installer backend subclass, bundled so its signature does not balloon into an unreadable parameter list (mirrors ServiceExtensionScriptGenerator.GeneratedLayout). GeneratedStoreTypeName is null for the Installer kind (no store was generated alongside the backend) and non-null for the Store kind.
VirtualizationEngine
Pure text engine that rewrites eligible public and protected member declarations to
public virtual / protected virtual — the mechanical half of ClassVirtualizer,
kept free of Unity/IO so its whole matching and refusal behavior is unit-testable on plain strings.
protected internal and private protected declarations are never touched. All-or-nothing
by design: any member whose qualifying-declaration count does not match its expected overload count
refuses the ENTIRE rewrite — a partially virtualized file is worse than an untouched one.
Enums
ExtensionPointKind
Every kind of Serenity extension point the Service Extension Creator can generate a concrete
implementation for. Service covers the original I{X}Service aggregates (see
AggregateCatalog); the rest cover the narrower ports beneath a service — the persistence
backend seam (Store/Installer), an aggregate's storage port
(Repository), an aggregate's outbound adapter port (Gateway), curated
infrastructure factories (Factory), and plain user classes with no Serenity contract at
all (Class — discovered lazily by DiscoverUserClasses(),
never part of the main catalog).
ServiceExtensionCreator.AsmdefMode
How the target folder's layered asmdefs are generated.
ServiceExtensionCreator.BaseLayer
Which layer the generated service is built on.
ServiceExtensionCreator.Style
The shape of the generated service class.
ServiceExtensionCreator.Wiring
How the generated service is registered into the IServiceLocator.
WiringCapability
How a discovered ExtensionPointDescriptor can be wired into the running game once a new implementation is generated for it. Unlike ServiceExtensionCreator.Wiring (a user choice for the Service kind), this describes what is NATURALLY available for a given extension point — Store, Repository, Gateway, Factory and Installer kinds each generate a fixed wiring shape dictated by their Kind, not a free user choice.