migrate-static-to-wrapper

Replace static dependency call sites with injected wrapper abstractions across a bounded C# scope.

Updated Aug 9, 2026
One-click install
npx skills add https://github.com/adinj00/player-performance --skill migrate-static-to-wrapper-adinj00
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: migrate-static-to-wrapper
Source: https://github.com/adinj00/player-performance/tree/main/.agents/skills/migrate-static-to-wrapper
Command: npx skills add https://github.com/adinj00/player-performance --skill migrate-static-to-wrapper-adinj00

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Static calls like DateTime.UtcNow and File.ReadAllText make C# code untestable and tightly coupled. This Skill performs codemod-style bulk replacement of those call sites with injected abstractions such as TimeProvider or IFileSystem, including constructor injection and test updates, within a bounded file, project, or namespace scope. ## Core Features & Use Cases - Bulk call-site replacement: Migrates DateTime.Now/UtcNow to TimeProvider, File.* to IFileSystem, and similar statics, with a mapping table that preserves DateTimeKind to avoid silent regressions. - Constructor injection and ambient seams: Adds constructor or primary-constructor parameters following existing naming conventions, and applies an ambient static seam pattern for static classes that cannot receive injection. - Test updates and build verification: Updates unit tests to use FakeTimeProvider or MockFileSystem, verifies DI registration, and runs dotnet build to confirm the migration compiles. - Use Case: Migrate all DateTime.UtcNow usages in one service project to TimeProvider, add the constructor parameter to affected classes, and update their tests to use a controllable fake clock. ## Quick Start Replace all DateTime.UtcNow calls in the Services project with TimeProvider, add constructor injection, and update the corresponding unit tests to use FakeTimeProvider.

Frequently Asked Questions about migrate-static-to-wrapper

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I replace DateTime.UtcNow with TimeProvider in C#?

Replace DateTime.UtcNow with _timeProvider.GetUtcNow().UtcDateTime and inject TimeProvider via the constructor. Using .UtcDateTime preserves the original DateTimeKind of Utc, avoiding silent behavioral regressions.

How do I migrate File.ReadAllText to IFileSystem?

Replace File.ReadAllText(path) with _fileSystem.File.ReadAllText(path), add using System.IO.Abstractions, and inject IFileSystem through the constructor. Verify the System.IO.Abstractions NuGet package is referenced and registered in DI first.

Can static classes use dependency injection in C#?

Static classes cannot receive constructor injection. Use an ambient context seam instead: a public static settable property defaulting to the real implementation, overridden in tests and always restored in a finally block, with parallel test execution disabled.

Why does migrating DateTime.UtcNow to TimeProvider change behavior?

TimeProvider.GetUtcNow() returns a DateTimeOffset, and its .DateTime property yields Kind == Unspecified instead of Utc. Use .UtcDateTime for former DateTime.UtcNow sites and .LocalDateTime for former DateTime.Now sites to preserve the original DateTimeKind.

When should I not use this static-to-wrapper migration approach?

Do not use it when no wrapper or abstraction exists yet, when you only want to detect statics rather than migrate them, or when migrating between test frameworks. Create and register the wrapper in DI first, then run the migration.