install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dotnet-guidelines" ~/.claude/skills/majiayu000-claude-skill-registry-dotnet-guidelines && rm -rf "$T"
manifest:
skills/data/dotnet-guidelines/SKILL.mdsource content
IMPORTANT Server Guidelines
- ALWAYS Use Primary Constructors for classes.
- ALWAYS Prefer
types for immutable data structures.record - NEVER mix multiple classes or DTOs in a single file, even if they are small. Filename ALWAYS matches the class or DTO name, for example
for aUserDto.cs
class.UserDto - Private fields should NOT be prefixed with
(e.g.,_
notrepository
)._repository - Add (.) to the end of all server-side log messages.
- Use
overstring?
for nullable strings.string - Use
for local variables when type is obvious.var - Don't use Regions in code files.
- Use Collection initializers for collections: instead of
, usenew List<string>()
, and instead ofnew() { "item1", "item2" }
uselist.ToArray()
.[.. list] - Use Anonymous function static: instead of
, uselist.Select(x => new Dto(x.SameProperty))
.list.Select(static x => new Dto(x.SameProperty)) - ALWAYS use
accessor for classes or records if not intended for inheritance.sealed - ALWAYS use
accessor for internal classes or records.internal - NEVER inject or create
andHttpClient
, instead use theIHttpClientFactory
interface.IRestClient - NEVER register services directly in
. Instead, use theIServiceCollection
,ITransientService
, orIScopedService
interfaces to register services with the appropriate lifetimes.ISingletonService - ALWAYS use
with Structured logging to log, no string interpolation and no other logging methods.ILogger - ALWAYS use cancellation tokens for asynchronous methods.
- ALWAYS use
for time-based in-memory caching, NEVER useIMemoryCore
.IMemoryCache - ALWAYS use Data Transfer Objects (DTO) for API communication, validated with attributes.
- ALWAYS use
as a parameter name in lambdas and anonymous functions.x - If any backend changes are made, run
in the root and ensure no build errors for the entire solution.dotnet build
Code Organization Principles
Avoid Unnecessary Wrapper Methods
Rule: Do NOT create wrapper methods for specific cases that simply call another method with fixed parameters. Call the base method directly instead.
Example - DON'T:
// ❌ Don't create this wrapper method for a single use case: public async Task<int> CreateAgentHistoryClearedMessageAsync(int sessionId) { var request = new CreateMessageRequest( Type: MessageType.System, Content: "Agent history has been cleared", Status: MessageStatus.Done ); return await CreateMessageAsync(sessionId, request); }
Example - DO:
// ✅ Instead, call CreateMessageAsync directly where needed: await messageService.CreateMessageAsync( sessionId, new CreateMessageRequest( MessageType.System, "Agent history has been cleared", MessageStatus.Done ) );
When to create a helper method:
- When there's complex logic beyond just parameter mapping
- When the same combination is used in multiple places (3+ times)
- When the method provides meaningful abstraction or validation