Skip to main content

designing-dotnet-types

Choose the right kind of .NET type for new behavior — static class, extension method, injected service, hosted service, options type, record, or interface. USE FOR: deciding how to shape a new unit of behavior or data before writing it, or reviewing that an existing type has the right shape for its dependencies and lifecycle. DO NOT USE FOR: registering a type or choosing its DI lifetime (use configuring-dotnet-dependency-injection).

설치로 이동

소스 정보

저장소
Nice3point/revit-skills
최근 소스 활동
2026년 7월 23일 12:21
감지된 SKILL.md 언어
영어
스타
13
포크
3

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
designing-dotnet-types
description
Choose the right kind of .NET type for new behavior — static class, extension method, injected service, hosted service, options type, record, or interface. USE FOR: deciding how to shape a new unit of behavior or data before writing it, or reviewing that an existing type has the right shape for its dependencies and lifecycle. DO NOT USE FOR: registering a type or choosing its DI lifetime (use configuring-dotnet-dependency-injection).
license
MIT
# Designing .NET Types Pick the type from its dependency and lifecycle needs, not from habit. ## When to use - Adding a new unit of behavior and deciding whether it is a static helper, an extension, a service, or a hosted service. - Adding data or configuration and deciding between a `record` and an options type. - Reviewing whether a type hides dependencies it should declare. ## Static classes Use a static class only for stateless behavior with no injected dependency, configuration, logging, I/O, clock, cache, or mutable state. Keep a static method deterministic for the same input unless its name says otherwise. ## Extension methods Use an extension method for a small operation centered on its receiver type, free of injected dependencies, I/O, hidden mutation, and expensive enumeration. Reach for an ordinary service the moment the operation needs configuration, logging, another collaborator, or a lifetime. ## Services Use an injected service when behavior depends on configuration, logging, I/O, a client, a clock, a cache, or another injectable collaborator. - Keep the service API focused on one capability boundary. - Use a primary constructor for dependencies; do not add fields that only mirror them. - Add an interface when a consumer must substitute the implementation, choose among implementations, or depend on a stable boundary; DI registration alone is not a reason. ## Hosted services Use `IHostedService` or `BackgroundService` for work that starts with the host, stops with the host, or continuously consumes an independent source. Keep request handling and one-shot operations in ordinary services. ## Data and configuration types Use a `record` for immutable data crossing a method, process, or configuration boundary. Use a dedicated options type for a cohesive configuration section; never store mutable configuration on a service. ## Validation - [ ] The type matches its dependency and lifecycle needs. - [ ] A static or extension method hides no I/O, mutation, or injected collaborator. - [ ] A service exposes one capability boundary. - [ ] An interface exists only for a real substitution or boundary need. ## Common Pitfalls | Pitfall | Correct approach | |-------------------------------------------------------|------------------------------------------------------------------------| | Static helper that quietly reads a file or clock | Make it a service with the dependency injected. | | Extension method taking a `DbContext` or `HttpClient` | Use a service; extensions are for receiver-centric operations. | | Interface added for every DI-registered class | Register the concrete type; add an interface only for a real boundary. | | Mutable "settings" service holding config | Bind an options type (use binding-and-validating-options). |
GitHub에서 보기