Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA standards. Use this skill to generate semantic ARIA for Web and accessibility traits for Web and Native platforms (iOS/Android).
中文简介正在准备中。当前显示原文说明。
Idiomatic C# and .NET patterns, conventions, dependency injection, async/await, and best practices for building robust, maintainable .NET applications.
中文简介正在准备中。当前显示原文说明。
实测评分 未实测
查看安装方法安装前可以查看交给 AI 代理的指令内容。
Idiomatic C# and .NET patterns for building robust, performant, and maintainable applications.
Use records and init-only properties for data models. Mutability should be an explicit, justified choice.
// Good: Immutable value object
public sealed record Money(decimal Amount, string Currency);
// Good: Immutable DTO with init setters
public sealed class CreateOrderRequest
{
public required string CustomerId { get; init; }
public required IReadOnlyList<OrderItem> Items { get; init; }
}
// Bad: Mutable model with public setters
public class Order
{
public string CustomerId { get; set; }
public List<OrderItem> Items { get; set; }
}
Be clear about nullability, access modifiers, and intent.
// Good: Explicit access modifiers and nullability
public sealed class UserService
{
private readonly IUserRepository _repository;
private readonly ILogger<UserService> _logger;
public UserService(IUserRepository repository, ILogger<UserService> logger)
{
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<User?> FindByIdAsync(Guid id, CancellationToken cancellationToken)
{
return await _repository.FindByIdAsync(id, cancellationToken);
}
}
Use interfaces for service boundaries. Register via DI container.
// Good: Interface-based dependency
public interface IOrderRepository
{
Task<Order?> FindByIdAsync(Guid id, CancellationToken cancellationToken);
Task<IReadOnlyList<Order>> FindByCustomerAsync(string customerId, CancellationToken cancellationToken);
Task AddAsync(Order order, CancellationToken cancellationToken);
}
// Registration
builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>();
// Good: Async all the way, with CancellationToken
public async Task<OrderSummary> GetOrderSummaryAsync(
Guid orderId,
CancellationToken cancellationToken)
{
var order = await _repository.FindByIdAsync(orderId, cancellationToken)
?? throw new NotFoundException($"Order {orderId} not found");
var customer = await _customerService.GetAsync(order.CustomerId, cancellationToken);
return new OrderSummary(order, customer);
}
// Bad: Blocking on async
public OrderSummary GetOrderSummary(Guid orderId)
{
var order = _repository.FindByIdAsync(orderId, CancellationToken.None).Result; // Deadlock risk
return new OrderSummary(order);
}
// Good: Concurrent independent operations
public async Task<DashboardData> LoadDashboardAsync(CancellationToken cancellationToken)
{
var ordersTask = _orderService.GetRecentAsync(cancellationToken);
var metricsTask = _metricsService.GetCurrentAsync(cancellationToken);
var alertsTask = _alertService.GetActiveAsync(cancellationToken);
await Task.WhenAll(ordersTask, metricsTask, alertsTask);
return new DashboardData(
Orders: await ordersTask,
Metrics: await metricsTask,
Alerts: await alertsTask);
}
Bind configuration sections to strongly-typed objects.
public sealed class SmtpOptions
{
public const string SectionName = "Smtp";
public required string Host { get; init; }
public required int Port { get; init; }
public required string Username { get; init; }
public bool UseSsl { get; init; } = true;
}
// Registration
builder.Services.Configure<SmtpOptions>(
builder.Configuration.GetSection(SmtpOptions.SectionName));
// Usage via injection
public class EmailService(IOptions<SmtpOptions> options)
{
private readonly SmtpOptions _smtp = options.Value;
}
Return explicit success/failure instead of throwing for expected failures.
public sealed record Result<T>
{
public bool IsSuccess { get; }
public T? Value { get; }
public string? Error { get; }
private Result(T value) { IsSuccess = true; Value = value; }
private Result(string error) { IsSuccess = false; Error = error; }
public static Result<T> Success(T value) => new(value);
public static Result<T> Failure(string error) => new(error);
}
// Usage
public async Task<Result<Order>> PlaceOrderAsync(CreateOrderRequest request)
{
if (request.Items.Count == 0)
return Result<Order>.Failure("Order must contain at least one item");
var order = Order.Create(request);
await _repository.AddAsync(order, CancellationToken.None);
return Result<Order>.Success(order);
}
public sealed class SqlOrderRepository : IOrderRepository
{
private readonly AppDbContext _db;
public SqlOrderRepository(AppDbContext db) => _db = db;
public async Task<Order?> FindByIdAsync(Guid id, CancellationToken cancellationToken)
{
return await _db.Orders
.Include(o => o.Items)
.AsNoTracking()
.FirstOrDefaultAsync(o => o.Id == id, cancellationToken);
}
public async Task<IReadOnlyList<Order>> FindByCustomerAsync(
string customerId,
CancellationToken cancellationToken)
{
return await _db.Orders
.Where(o => o.CustomerId == customerId)
.OrderByDescending(o => o.CreatedAt)
.AsNoTracking()
.ToListAsync(cancellationToken);
}
public async Task AddAsync(Order order, CancellationToken cancellationToken)
{
_db.Orders.Add(order);
await _db.SaveChangesAsync(cancellationToken);
}
}
// Custom middleware
public sealed class RequestTimingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<RequestTimingMiddleware> _logger;
public RequestTimingMiddleware(RequestDelegate next, ILogger<RequestTimingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
var stopwatch = Stopwatch.StartNew();
try
{
await _next(context);
}
finally
{
stopwatch.Stop();
_logger.LogInformation(
"Request {Method} {Path} completed in {ElapsedMs}ms with status {StatusCode}",
context.Request.Method,
context.Request.Path,
stopwatch.ElapsedMilliseconds,
context.Response.StatusCode);
}
}
}
// Organized with route groups
var orders = app.MapGroup("/api/orders")
.RequireAuthorization()
.WithTags("Orders");
orders.MapGet("/{id:guid}", async (
Guid id,
IOrderRepository repository,
CancellationToken cancellationToken) =>
{
var order = await repository.FindByIdAsync(id, cancellationToken);
return order is not null
? TypedResults.Ok(order)
: TypedResults.NotFound();
});
orders.MapPost("/", async (
CreateOrderRequest request,
IOrderService service,
CancellationToken cancellationToken) =>
{
var result = await service.PlaceOrderAsync(request, cancellationToken);
return result.IsSuccess
? TypedResults.Created($"/api/orders/{result.Value!.Id}", result.Value)
: TypedResults.BadRequest(result.Error);
});
// Good: Early returns with clear validation
public async Task<ProcessResult> ProcessPaymentAsync(
PaymentRequest request,
CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(request);
if (request.Amount <= 0)
throw new ArgumentOutOfRangeException(nameof(request.Amount), "Amount must be positive");
if (string.IsNullOrWhiteSpace(request.Currency))
throw new ArgumentException("Currency is required", nameof(request.Currency));
// Happy path continues here without nesting
var gateway = _gatewayFactory.Create(request.Currency);
return await gateway.ChargeAsync(request, cancellationToken);
}
| Anti-Pattern | Fix |
|---|---|
async void methods | Return Task (except event handlers) |
.Result or .Wait() | Use await |
catch (Exception) { } | Handle or rethrow with context |
new Service() in constructors | Use constructor injection |
public fields | Use properties with appropriate accessors |
dynamic in business logic | Use generics or explicit types |
Mutable static state | Use DI scoping or ConcurrentDictionary |
string.Format in loops | Use StringBuilder or interpolated string handlers |
还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA standards. Use this skill to generate semantic ARIA for Web and accessibility traits for Web and Native platforms (iOS/Android).
中文简介正在准备中。当前显示原文说明。
Whole site or product — a full web accessibility (a11y) audit against WCAG 2.2, following the WCAG-EM methodology. Defines scope, samples representative pages and flows, runs the automated tier (`accessibility-scan`) and the hands-on manual tier (`accessibility-inspect`), and produces one conformance report. Grades each finding by severity and evidence basis, and states per-criterion conformance as pass, fail, or undetermined (needs a human). Use it for 'audit my site for accessibility', 'is this product accessible', 'a11y audit', 'WCAG or Section 508 conformance report', or any multi-page assessment. Assesses; does not fix (use `accessibility-fix`) or diff (use `accessibility-diff`). For a single page use `accessibility-scan`; for hands-on keyboard and screen-reader checks use `accessibility-inspect`.
中文简介正在准备中。当前显示原文说明。
Regression check — diff a live page's web accessibility (a11y) violations against a baseline. By default it compares your uncommitted changes (stash-based); pass `--branch [<name>]` to compare against a branch. Reports the new WCAG violations introduced, the ones fixed, and the count of pre-existing ones. Use it for 'did my change break accessibility', 'what a11y issues did this PR add', or as a CI gate. For a full scan of one page use `accessibility-scan`; for a whole site use `accessibility-audit`.
中文简介正在准备中。当前显示原文说明。
Remediation only — repair web accessibility (a11y) violations against WCAG 2.2 with a baseline, edit, and verify loop. Takes a target (URL, files, directory) or a findings worklist from `accessibility-scan`/`accessibility-inspect`/`accessibility-audit`, applies mechanical fixes as given, leaves TODOs for visual or contextual judgment, and verifies by re-running the baseline check. It only fixes. To find issues use `accessibility-scan` (one page, automated), `accessibility-inspect` (one page, manual), or `accessibility-audit` (whole site, WCAG-EM); to check for regressions use `accessibility-diff`. Use it for 'fix the a11y issues in X', 'make this accessible', 'add missing alt text and labels', 'apply these accessibility fixes', 'remediate these violations'.
中文简介正在准备中。当前显示原文说明。
One page, hands-on manual tier — drive a live page through the web accessibility (a11y) checks a rule engine can't decide: keyboard operation and focus order, screen-reader names, roles and states from the accessibility tree, reflow and zoom, reduced motion, form errors, and target size. Grades each finding by evidence basis (verified / confirm-with-a-human / human-required) and severity, and closes every criterion in a ledger: verified, flagged, not exercised, or N/A. Locates and assesses; does not fix (use `accessibility-fix`). Use it for keyboard testing, focus-order checks, screen-reader or a11y-tree review, reflow and zoom at 200%, or 'is this operable, not just lint-clean'. The automated tier is `accessibility-scan`; `accessibility-audit` runs both across a sampled site.
中文简介正在准备中。当前显示原文说明。
One page, automated tier — run the web accessibility (a11y) rule engine against a live page and locate every violation it can detect mechanically. Pass a URL, a config target name (e.g. `accesslint:accessibility-scan dev`), or nothing to use the default target from `accesslint.config.json`. Ensures a debuggable Chrome, runs the @accesslint/core engine over CDP, and returns a worklist of live-DOM WCAG 2.2 violations, each grounded to its DOM selector and source `file:line`. Locates; doesn't edit. Use it for 'is this page accessible', 'check a11y on this URL', 'find contrast and alt-text issues', or to verify a UI change. For hands-on keyboard and screen-reader checks use `accessibility-inspect`; for a whole site or product use `accessibility-audit`; to diff against uncommitted changes or a branch use `accessibility-diff`.
中文简介正在准备中。当前显示原文说明。