Skip to main content
Version: v1.7.1

Registration

This page covers how to register custom repositories with the DI container using the Kista fluent builder API.

Basic Registration

Use AddRepository<T>() on the repository context builder. The driver's open-generic registrations (e.g. InMemoryRepository<> from .UseInMemory()) serve as defaults for all entities; AddRepository<T>() registers a concrete type that overrides the open generic for that specific entity:

builder.Services.AddRepositoryContext()
.UseInMemory() // default: InMemoryRepository for all entities
.AddRepository<SpecialProductRepo>(); // override: SpecialProductRepo for Product only
builder.Services.AddRepositoryContext()
.UseEntityFramework<AppDbContext>(b => b
.ConfigureDbContext(opts => opts.UseSqlServer("...")))
.AddRepository<ProductRepository>();

What Gets Registered

The AddRepository<T>() method scans the specified type and registers all relevant services:

builder.Services.AddRepositoryContext()
.UseInMemory()
.AddRepository<ProductRepository>();

This registers:

Service TypeDescription
ProductRepositoryThe concrete implementation
IProductRepositoryYour custom interface
IRepository<Product, Guid>The base repository contract

All registrations are scoped by default, matching the typical request lifetime for data access.

Lifetime Configuration

Override the default lifetime:

builder.Services.AddRepositoryContext()
.UseInMemory()
.AddRepository<ProductRepository>(ServiceLifetime.Singleton);

Available lifetimes:

LifetimeUse Case
Scoped (default)Request-scoped data access, typical web apps
TransientStateless repositories, no shared state
SingletonRead-only repositories, cached data

Open Generic Repositories

Open generic repositories are registered as open generics:

public class NamedEntityRepository<TEntity> : Repository<TEntity, Guid>, INamedEntityRepository<TEntity>
where TEntity : class, INamedEntity {
// ...
}

builder.Services.AddRepositoryContext()
.UseEntityFramework<AppDbContext>()
.AddRepository(typeof(NamedEntityRepository<>));

This allows resolution of INamedEntityRepository<Product>, INamedEntityRepository<Category>, etc.

Multiple Repositories

Register multiple repositories in sequence:

builder.Services.AddRepositoryContext()
.UseEntityFramework<AppDbContext>()
.AddRepository<ProductRepository>()
.AddRepository<OrderRepository>()
.AddRepository<CustomerRepository>();

Or chain them:

var context = builder.Services.AddRepositoryContext()
.UseEntityFramework<AppDbContext>();

context.AddRepository<ProductRepository>();
context.AddRepository<OrderRepository>();
context.AddRepository<CustomerRepository>();

Assembly Scanning

Use ScanRepositories() to automatically discover and register repository types from one or more assemblies:

builder.Services.AddRepositoryContext()
.UseEntityFramework<AppDbContext>()
.ScanRepositories(typeof(ProductRepository).Assembly);

This scans the assembly for all types that implement IRepository<TEntity> and registers them automatically.

Consuming the Repository

After registration, resolve the repository through DI:

public class ProductService {
private readonly IProductRepository _products;

public ProductService(IProductRepository products) {
_products = products;
}

public async Task<Product?> GetByCodeAsync(string code, CancellationToken ct = default) {
return await _products.FindByCodeAsync(code, ct);
}
}

You can also resolve the base interface:

public class GenericService {
private readonly IRepository<Product, Guid> _products;

public GenericService(IRepository<Product, Guid> products) {
_products = products;
}

public async Task<Product?> GetByIdAsync(Guid id, CancellationToken ct = default) {
return await _products.FindAsync(id, ct);
}
}

Removed Interface Registration

The legacy extension interfaces (IQueryableRepository, IPageableRepository, IFilterableRepository) were removed in 1.7.1 and are no longer registered by AddRepository<T>() or ScanRepositories() — they do not exist in the framework. Resolve IRepository<TEntity> or your custom interface instead.

If you are upgrading from 1.7.0 and have repositories that explicitly implement these interfaces, see the Migration from 1.7 guide for the steps to drop the declarations and move to the protected-member model.