xiaohongshu
xiaohongshu
dependency-injection-review
Review code for proper DI patterns using DryIoc. Ensures no static singletons, validates constructor injection and service lifetimes. Use when reviewing code, refactoring static access, or debugging DI issues.
Full skill instructions
This skill audits code for adherence to the game engine's dependency injection architecture using DryIoc. It ensures all services use constructor injection, identifies static singleton violations, and validates service registration patterns.
Invoke this skill when:
Program.csnew() for servicesNEVER create static singletons! All singleton instances must be registered in the DI container.
The ONLY acceptable static classes are pure constant classes:
EditorUIConstants - UI sizing and styling constantsRenderingConstants - Rendering configuration constantsEverything else uses dependency injection.
All dependencies must be injected through the primary constructor.
✅ CORRECT (Use Primary Constructor):
public class AnimationSystem(
ITextureFactory textureFactory,
IResourceManager resourceManager) : ISystem
{
// Dependencies are automatically available as private readonly fields
// Use textureFactory and resourceManager directly in methods
}
❌ FORBIDDEN - Static Singleton:
public class AnimationSystem
{
private static AnimationSystem? _instance;
public static AnimationSystem Instance => _instance ??= new AnimationSystem();
private AnimationSystem() { } // Private constructor
}
❌ FORBIDDEN - Property Injection:
public class AnimationSystem
{
public ITextureFactory TextureFactory { get; set; } // Don't use property injection!
public AnimationSystem() { }
}
❌ FORBIDDEN - Service Locator Pattern:
public class AnimationSystem
{
private readonly ITextureFactory _textureFactory;
public AnimationSystem()
{
// Don't resolve from container directly!
_textureFactory = ServiceLocator.Resolve<ITextureFactory>();
}
}
Location: Editor/Program.cs or Runtime/Program.cs
Service Lifetime Guidelines:
Example: Editor/Program.cs Registration:
// Core managers (Singleton)
container.Register<ISceneManager, SceneManager>(Reuse.Singleton);
container.Register<IProjectManager, ProjectManager>(Reuse.Singleton);
container.Register<ISelectionManager, SelectionManager>(Reuse.Singleton);
// Factories (Singleton)
container.Register<ITextureFactory, TextureFactory>(Reuse.Singleton);
container.Register<IShaderFactory, ShaderFactory>(Reuse.Singleton);
// Panels (Singleton)
container.Register<ContentBrowserPanel>(Reuse.Singleton);
container.Register<ConsolePanel>(Reuse.Singleton);
container.Register<PropertiesPanel>(Reuse.Singleton);
// Systems (Singleton)
container.Register<RenderingSystem>(Reuse.Singleton);
container.Register<AnimationSystem>(Reuse.Singleton);
// Transient services
container.Register<IValidationService, ValidationService>(Reuse.Transient);
Use interfaces for services that need abstraction, testability, or multiple implementations.
✅ USE INTERFACES FOR:
// Managers - multiple implementations or testability
public interface ISceneManager
{
Scene? ActiveScene { get; }
void LoadScene(string path);
}
public class SceneManager(IDependency dep) : ISceneManager { }
// Factories - abstraction from creation logic
public interface ITextureFactory
{
Texture2D CreateTexture(string path);
}
public class TextureFactory(ICache cache) : ITextureFactory { }
// Cross-cutting concerns - different implementations per platform
public interface IRendererAPI
{
void DrawIndexed(uint indexCount);
}
public class OpenGLRendererAPI(IContext context) : IRendererAPI { }
✅ SKIP INTERFACES FOR:
// Editor panels - concrete UI implementations
public class ConsolePanel(ILogger logger) { }
// ECS Systems - concrete game logic
public class AnimationSystem(ITextureFactory factory) : ISystem { }
// Pure data classes - no behavior to abstract
public class Transform
{
public Vector3 Position { get; set; }
public Vector3 Rotation { get; set; }
}
// Component Editors - concrete UI for specific components
public class TransformComponentEditor(IFieldEditor<Vector3> vector3Editor) { }
Decision Guide:
❌ FORBIDDEN:
// Service A depends on Service B
public class ServiceA
{
public ServiceA(IServiceB serviceB) { }
}
// Service B depends on Service A - CIRCULAR!
public class ServiceB
{
public ServiceB(IServiceA serviceA) { }
}
✅ SOLUTIONS:
Option 1: Extract shared dependency
public class ServiceA
{
public ServiceA(ISharedService shared) { }
}
public class ServiceB
{
public ServiceB(ISharedService shared) { }
}
Option 2: Use events for decoupling
public class ServiceA
{
public event Action<Data>? OnDataChanged;
}
public class ServiceB(IServiceA serviceA)
{
// Subscribe to events in constructor body or init method
public void Initialize()
{
serviceA.OnDataChanged += HandleDataChanged;
}
}
Option 3: Pass data directly
// Instead of injecting the whole service, pass only the data needed
public class ServiceA
{
public Data GetData() => _data;
}
public class ServiceB
{
public void ProcessData(Data data) // Method parameter, not constructor
{
// Process data without depending on ServiceA
}
}
Decision Tree - Choosing a Solution:
// Service with dependencies (using primary constructor)
public class AnimationSystem(ITextureFactory textureFactory) : ISystem
{
// Use textureFactory in methods
}
// Simple registration - DryIoc auto-resolves dependencies
container.Register<AnimationSystem>(Reuse.Singleton);
// Service needing initialization
container.Register<ISceneManager, SceneManager>(
Reuse.Singleton,
setup: Setup.With(allowDisposableTransient: true));
When reviewing code for DI compliance, follow this systematic approach:
Scan for static singletons:
grep -r "static.*Instance" --include="*.cs" Engine/ Editor/ | grep -v "Constants.cs"
Check constructor injection:
Validate registrations:
Editor/Program.cs or Runtime/Program.csVerify service lifetimes:
Test resolution:
For detailed troubleshooting steps, common error solutions, and automated validation scripts with expected outputs, see the Debugging Guide.
Quick validation commands:
grep -rn "static.*Instance.*=>" --include="*.cs" Engine/ Editor/ | grep -v "Constants.cs"grep -rn "ServiceLocator\|\.Resolve<" --include="*.cs" Engine/ Editor/grep -rn "{ get; set; }.*Factory\|{ get; set; }.*Manager" --include="*.cs" Engine/ Editor/xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience