# DI best practices

Smartstore relies on [Autofac](https://autofac.readthedocs.io/en/latest/) for dependency injection but modules typically register services in a `Startup` class derived from `StarterBase`. Inside `ConfigureServices` you can access the ASP.NET Core `IServiceCollection` and the `IApplicationContext`:

```csharp
internal class Startup : StarterBase
{
    public override void ConfigureServices(IServiceCollection services, IApplicationContext appContext)
    {
        services.Configure<MvcOptions>(o =>
        {
            o.Filters.AddEndpointFilter<StripeScriptIncludeFilter, PublicController>().WhenNonAjax();
        });

        if (appContext.IsInstalled)
        {
            services.AddScoped<StripeHelper>();
        }

        // override an existing service: last registration wins
        services.AddScoped<IPriceCalculationService, CustomPriceCalculationService>();
    }
}
```

The following tips help keeping components testable and scopes well defined.

## ICommonServices

`ICommonServices` bundles frequently used helpers such as `IWorkContext`, `StoreContext`, and the `SmartDbContext`. In controllers or view components deriving from `SmartController` or `SmartViewComponent`, it is property-injected and available via the `Services` member without constructor parameters:

```csharp
public class SampleController : SmartController
{
    public IActionResult Index()
    {
        var customer = Services.WorkContext.CurrentCustomer;
        return View();
    }
}
```

Inject it manually only in other classes that need many of its helpers to keep dependencies explicit.

## ILifetimeScopeAccessor

Use `ILifetimeScopeAccessor` to obtain or create scopes outside the request pipeline, e.g. for background jobs or CLI tools. `BeginContextAwareScope` returns a scope that reuses the HTTP scope when available or creates a new one otherwise.

```csharp
using var _ = _scopeAccessor.BeginContextAwareScope(out var scope);
var service = scope.Resolve<IMyService>();
```

## Work

`Work<T>` lazily resolves services from the current scope. It is useful when a service is required only occasionally or within loops, avoiding unnecessary constructions.

```csharp
public class Sample
{
    private readonly Work<IMyService> _work;
    public Sample(Work<IMyService> work) => _work = work;

    public void DoSomething() => _work.Value.Execute();
}
```

By following these guidelines, modules stay lightweight and lifetimes remain predictable.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.smartstore.com/framework/advanced/di-best-practices.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
