# Configuring Dotnet Dependency Injection

> >

- **Type:** Skill
- **Install:** `agentstack add skill-nice3point-revit-skills-configuring-dotnet-dependency-injection`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Nice3point](https://agentstack.voostack.com/s/nice3point)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Nice3point](https://github.com/Nice3point)
- **Source:** https://github.com/Nice3point/revit-skills/tree/main/plugins/dotnet-advanced/skills/configuring-dotnet-dependency-injection

## Install

```sh
agentstack add skill-nice3point-revit-skills-configuring-dotnet-dependency-injection
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Configuring .NET Dependency Injection

Register a service in the composition that owns its lifetime, grouped with the capability it belongs to.

## When to use

- Adding or reviewing an `IServiceCollection` registration.
- Choosing a lifetime, or debugging a captive-dependency or disposal problem.
- Scanning an assembly for conventional registrations.

## Workflow

### Step 1: Register with the owning capability

Group the registration in a feature extension method that returns `IServiceCollection` for fluent chaining, rather than scattering `AddX` calls across the composition root.

```csharp
public static class EmailServiceCollectionExtensions
{
    extension(IServiceCollection services)
    {
        public IServiceCollection AddEmailSending()
        {
            services.AddSingleton();

            return services;
        }
    }
}
```

### Step 2: Choose the lifetime from state and concurrency

- **Singleton** — thread-safe, process-wide state, or a resource owned for the process lifetime.
- **Scoped** — one instance per operation, when the host opens a scope per Window, operation, endpoint.
- **Transient** — lightweight, stateless, constructed per consumer.

Never inject a scoped service into a singleton, and never make a service singleton when it holds per-operation mutable state.

### Step 3: Register an interface only for a real boundary

Register the concrete type when no consumer needs an abstraction; register `interface + implementation` when a consumer depends on an intentional seam.
Register a hosted service separately from its ordinary contract when both resolve to the same process-owned instance.

### Step 4: Scan when registrations are conventional

Use Scrutor's `Scan` to register many types by convention instead of listing each, when they share a marker interface or naming pattern.

```csharp
services.Scan(scan => scan
    .FromAssemblyOf()
    .AddClasses(classes => classes.AssignableTo())
    .AsImplementedInterfaces()
    .WithTransientLifetime());
```

### Step 5: Create an extension for group registration

Move every registration group — a set of related `AddX` calls or a Scrutor `Scan` — into its capability's extension method, and let the host composition root call only those methods.
Registration detail never lives at the place the host is configured.

Declare the extension with a C# 14 extension block so the `IServiceCollection` receiver is named once for the whole capability:

```csharp
public static class EmailServiceCollectionExtensions
{
    extension(IServiceCollection services)
    {
        public IServiceCollection AddEmailSenders()
        {
            services.AddSingleton();

            services.Scan(scan => scan
                .FromAssemblyOf()
                .AddClasses(classes => classes.AssignableTo())
                .AsImplementedInterfaces()
                .WithSingletonLifetime());

            return services;
        }
    }
}
```

The composition root then reads as a flat list of capabilities, with no `AddX` or `Scan` detail inlined:

```csharp
services.AddEmailSenders();
```

### Step 6: Verify the graph

Build the host through its normal entry point and resolve the changed service through the owning path or a focused composition test.
Never construct a second `ServiceProvider` in production registration code.

## Validation

- [ ] The host that owns the behavior owns the registration.
- [ ] The lifetime matches state, concurrency, and disposal needs.
- [ ] No singleton captures a scoped or transient dependency.
- [ ] Registrations are grouped with their capability, and the normal host composition succeeds.
- [ ] The composition root calls only capability extension methods; no `AddX` group or Scrutor `Scan` is inlined where the host is configured.

## Common Pitfalls

| Pitfall                                                             | Correct approach                                                                        |
|---------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
| Scoped service injected into a singleton                            | Make the consumer scoped, or pass a factory / `IServiceScopeFactory`.                   |
| Singleton holding per-request mutable state                         | Use scoped or transient.                                                                |
| `Scan` not found                                                    | The `Scrutor` package is not referenced in the project.                                 |
| A second `new ServiceProvider()` to resolve something               | Resolve through the real host or a composition test.                                    |
| `AddX` group or Scrutor `Scan` inlined where the host is configured | Wrap it in a capability extension (e.g. `AddEmailSenders`) and call that from the root. |

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Nice3point](https://github.com/Nice3point)
- **Source:** [Nice3point/revit-skills](https://github.com/Nice3point/revit-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-nice3point-revit-skills-configuring-dotnet-dependency-injection
- Seller: https://agentstack.voostack.com/s/nice3point
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
