migrate-static-to-wrapper

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

Updated Jul 12, 2026
One-click install
npx skills add https://github.com/Patrick-Rex/DotNetTechSamples --skill migrate-static-to-wrapper-patrick-rex
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: migrate-static-to-wrapper
Source: https://github.com/Patrick-Rex/DotNetTechSamples/tree/main/.agents/plugins/dotnet-test/skills/migrate-static-to-wrapper
Command: npx skills add https://github.com/Patrick-Rex/DotNetTechSamples --skill migrate-static-to-wrapper-patrick-rex

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Static calls like DateTime.UtcNow and File.ReadAllText make .NET code untestable and hard to control in unit tests. This Skill performs codemod-style bulk replacement of those static 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 - Mechanical call-site replacement: Maps static calls (DateTime.Now/UtcNow, File.*, Directory.Exists, Environment, Console, Process) to their wrapper equivalents while preserving DateTimeKind and surrounding code structure. - 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 migration: Updates affected unit tests to use FakeTimeProvider, MockFileSystem, or mocks, and verifies the result with dotnet build. - Use Case: Migrate DateTime.UtcNow to TimeProvider across one service project, adding constructor injection to affected classes and switching their tests to FakeTimeProvider, then confirm the build passes. ## Quick Start Replace all DateTime.UtcNow calls in the Services project with TimeProvider, add constructor injection, and update the 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 through the class constructor. Use .UtcDateTime rather than .DateTime so the resulting DateTime keeps Kind == Utc, then register TimeProvider in Program.cs.

How to migrate File.ReadAllText to IFileSystem for testability?

Replace File.ReadAllText(path) with _fileSystem.File.ReadAllText(path), add an IFileSystem constructor parameter, and add the System.IO.Abstractions using directive and NuGet package. Update tests to use MockFileSystem from System.IO.Abstractions.TestingHelpers.

Can static classes use dependency injection in .NET?

Static classes cannot receive constructor injection, so use an ambient seam instead: a public static settable property defaulting to the real implementation, such as TimeProvider.System. Tests override it with a fake, restore it in a finally block, and must not run in parallel.

Why does migrating DateTime.UtcNow to TimeProvider break behavior?

The common cause is using DateTimeOffset.DateTime, which returns 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. Generate or register the wrapper first, then run the migration one project or namespace at a time.