logo SERENITY
Game Systems Foundation
Search Results for

    Show / Hide Table of Contents

    Class 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.

    Inheritance
    object
    AsmdefReferenceWriter
    Inherited Members
    object.ToString()
    object.Equals(object)
    object.Equals(object, object)
    object.ReferenceEquals(object, object)
    object.GetHashCode()
    object.GetType()
    object.MemberwiseClone()
    Namespace: Serenity.ServiceExtensionCreator.Editor
    Assembly: Serenity.ServiceExtensionCreator.Editor.dll
    Syntax
    public static class AsmdefReferenceWriter

    Methods

    AppendTaskToProfile(UnityInitializationPipelineProfile, UnityReflectionCallTaskDefinition, out string)

    Appends taskDefinition to profile's Tasks list (idempotent — a task already present is not duplicated). The caller resolves the target profile first via TryResolveSingleProfile(out UnityInitializationPipelineProfile, out string), which keeps this method directly unit-testable against a scratch profile asset.

    Declaration
    public static bool AppendTaskToProfile(UnityInitializationPipelineProfile profile, UnityReflectionCallTaskDefinition taskDefinition, out string warning)
    Parameters
    Type Name Description
    UnityInitializationPipelineProfile profile
    UnityReflectionCallTaskDefinition taskDefinition
    string warning
    Returns
    Type Description
    bool

    CreateAsmdef(string, string, string, IReadOnlyCollection<string>, bool)

    Writes a brand-new asmdef at {folderPath}/{assemblyName}.asmdef — every generated layer owns its own folder, so this never mutates an existing asmdef. testAssembly applies the shape every generated test asmdef in this project shares (mirrors Assets/Serenity/Tests/Tests.asmdef): an nunit precompiled reference, the UNITY_INCLUDE_TESTS define constraint, overridden references, and not auto-referenced.

    Declaration
    public static string CreateAsmdef(string folderPath, string assemblyName, string rootNamespace, IReadOnlyCollection<string> references, bool testAssembly = false)
    Parameters
    Type Name Description
    string folderPath
    string assemblyName
    string rootNamespace
    IReadOnlyCollection<string> references
    bool testAssembly
    Returns
    Type Description
    string

    ExtensionPointInstallationReferences(ExtensionPointDescriptor, Style, string, bool, Type)

    The asmdef reference names a generated Store/Repository/Gateway/Installer Installation layer needs: everything the code layer needs (when one was generated — the Installer kind has none), codeLayerAssemblyName itself (for the generated class type the wiring constructs), and every assembly in wiringBaseType's own base-class chain — the type the wiring subclasses (the aggregate's Unity{X}Installer for Repository/Gateway, or PersistenceInstaller for Store/Installer). The base-class chain matters because the C# compiler must resolve a named base type's OWN base classes too (CS0012 fires otherwise) — e.g. UnityScoreInstaller lives in Serenity.UnityScore.Installation but its base ScoreInstaller lives in the separate Serenity.Score.Installation assembly, and Unity asmdef references are not transitive.

    Declaration
    public static IReadOnlyCollection<string> ExtensionPointInstallationReferences(ExtensionPointDescriptor descriptor, ServiceExtensionCreator.Style style, string codeLayerAssemblyName, bool hasCodeLayerClass, Type wiringBaseType)
    Parameters
    Type Name Description
    ExtensionPointDescriptor descriptor
    ServiceExtensionCreator.Style style
    string codeLayerAssemblyName
    bool hasCodeLayerClass
    Type wiringBaseType
    Returns
    Type Description
    IReadOnlyCollection<string>

    HasTestFrameworkAccess(string)

    True when the asmdef governing folder (or Assembly-CSharp when none governs it) already exposes NUnit/TestRunner access — the cheap, generically-detectable signal for whether a generated test stub would actually compile when Skip leaves it joining the ambient assembly instead of a dedicated generated Tests asmdef. Assembly-CSharp itself is assumed to lack this access, matching this project's convention of never enabling "Test Assemblies" for it.

    Declaration
    public static bool HasTestFrameworkAccess(string folder)
    Parameters
    Type Name Description
    string folder
    Returns
    Type Description
    bool

    InstallationReferences(AggregateDescriptor, Style, Wiring, string)

    The asmdef reference names the generated Installation layer needs: everything the code layer needs directly — Unity asmdef references are NOT transitive, so referencing codeLayerAssemblyName alone would not re-expose Serenity.Global.Application or the aggregate's interface assembly to the wiring script that names them directly — plus codeLayerAssemblyName itself (for the constructed service type), and, for PipelineReplace, the assembly hosting UnityReflectionCallTaskDefinition so a hand-written extension of the generated wiring can reach the task type without a manual asmdef edit.

    Declaration
    public static IReadOnlyCollection<string> InstallationReferences(AggregateDescriptor descriptor, ServiceExtensionCreator.Style style, ServiceExtensionCreator.Wiring wiring, string codeLayerAssemblyName)
    Parameters
    Type Name Description
    AggregateDescriptor descriptor
    ServiceExtensionCreator.Style style
    ServiceExtensionCreator.Wiring wiring
    string codeLayerAssemblyName
    Returns
    Type Description
    IReadOnlyCollection<string>

    RequiredReferences(AggregateDescriptor, Style, Wiring)

    The asmdef reference NAMES the generated code layer (Business/Application or Infrastructure) needs. Resolved from the actual compiled assemblies via reflection rather than a naming convention — several Serenity modules (GameSettings, EventDispatcher, FilePersistence, ServiceLocator, Logging among them) fold their Application layer into Serenity.Global.Application via .asmref instead of shipping their own asmdef, so a convention-based "Serenity.{Agg}.Application" guess would be wrong for those. "Serenity.Global.Application" is always included: it hosts IService/ILogService/IServiceLocator/AutoRegisterServiceAttribute. "Serenity.Global.Domain" is always included too: IService : IFoundationSettings, and IFoundationSettings lives in that separate assembly — a generated class implementing (or a wiring script referencing) any I{X}Service touches it transitively through the interface hierarchy, and Unity asmdef references are NOT transitive, so it must be listed explicitly. Neither is re-exposed by referencing the aggregate's own interface assembly alone. On top of that fixed set, every assembly touched by the generated members' SIGNATURES is unioned in — the same Serenity.ServiceExtensionCreator.Editor.AsmdefReferenceWriter.CollectMemberAssemblyNames(System.Collections.Generic.IReadOnlyList{System.Reflection.MemberInfo}) collector the extension-point kinds use: the interface members for every style (e.g. IScoreService's members name ScoreKey/ScoreSnapshot from the separate Serenity.Score.Domain assembly, which the fixed set alone omits — a real field-tested CS0246/CS0012), plus — for InfrastructureSubclass — the concrete base's public virtual member and constructor signatures and its base-class chain (Serenity.ServiceExtensionCreator.Editor.AsmdefReferenceWriter.CollectSubclassBaseAssemblyNames(System.Type)), since the generated overrides and forwarding constructors restate those signatures in source.

    Declaration
    public static IReadOnlyCollection<string> RequiredReferences(AggregateDescriptor descriptor, ServiceExtensionCreator.Style style, ServiceExtensionCreator.Wiring wiring)
    Parameters
    Type Name Description
    AggregateDescriptor descriptor
    ServiceExtensionCreator.Style style
    ServiceExtensionCreator.Wiring wiring
    Returns
    Type Description
    IReadOnlyCollection<string>

    RequiredReferences(ExtensionPointDescriptor, Style, Type)

    The asmdef reference names a generated Store/Repository/Gateway/Factory code layer needs: the contract's own assembly, the subclassed base's assembly plus its base-class chain and restated member/constructor signature assemblies when subclassing (InfrastructureSubclass style — the base is subclassBaseOverride when the user picked one, the descriptor's reference concrete otherwise), and — unlike RequiredReferences(AggregateDescriptor, Style, Wiring), which leans on every Serenity service interface's members staying within its own assembly boundary — every assembly touched by the contract's own member signatures (Serenity.ServiceExtensionCreator.Editor.AsmdefReferenceWriter.CollectMemberAssemblyNames(System.Collections.Generic.IReadOnlyList{System.Reflection.MemberInfo})), since some modules (e.g. Score: Serenity.Score.Application vs Serenity.Score.Domain) split their interface from its parameter/return DTO types across two real, separate assemblies. No assembly is unconditionally included — these contracts do not extend IService, so there is no Serenity.Global.Application/Serenity.Global.Domain dependency to guarantee.

    Declaration
    public static IReadOnlyCollection<string> RequiredReferences(ExtensionPointDescriptor descriptor, ServiceExtensionCreator.Style style, Type subclassBaseOverride = null)
    Parameters
    Type Name Description
    ExtensionPointDescriptor descriptor
    ServiceExtensionCreator.Style style
    Type subclassBaseOverride
    Returns
    Type Description
    IReadOnlyCollection<string>

    ResolveNearestAssemblyName(string)

    Walks up from folder to the nearest .asmdef and returns its assembly name, or "Assembly-CSharp" when no asmdef governs the folder. Mirrors ModalCreator.ResolveAssemblyName. Used to resolve the ambient assembly a generated file joins when Skip leaves no dedicated asmdef behind.

    Declaration
    public static string ResolveNearestAssemblyName(string folder)
    Parameters
    Type Name Description
    string folder
    Returns
    Type Description
    string

    TryResolvePipelineProfileName(out string, out string)

    Resolves the same target profile as TryResolveSingleProfile(out UnityInitializationPipelineProfile, out string), exposing only its name — used for a read-only wizard preview of which profile the PipelineReplace task would append to.

    Declaration
    public static bool TryResolvePipelineProfileName(out string profileName, out string warning)
    Parameters
    Type Name Description
    string profileName
    string warning
    Returns
    Type Description
    bool

    TryResolveSingleProfile(out UnityInitializationPipelineProfile, out string)

    Resolves the project's single UnityInitializationPipelineProfile asset, without mutating anything — the robust signal for "this is the profile the game actually uses" without depending on a scene being open or on UnitySerenityInstaller (which lives in Assembly-CSharp and cannot be referenced from this asmdef). Ambiguous or missing profiles return false with an explanatory warning that lists every candidate asset path when more than one was found.

    Declaration
    public static bool TryResolveSingleProfile(out UnityInitializationPipelineProfile profile, out string warning)
    Parameters
    Type Name Description
    UnityInitializationPipelineProfile profile
    string warning
    Returns
    Type Description
    bool
    In this article
    © 2026 Serenity. All Rights Reserved