Skip to content

Dependency Injection

Tayra integrates with the standard Microsoft.Extensions.DependencyInjection container. The AddTayra() extension method registers all required services, including a built-in in-memory key store, and returns a TayraBuilder for further configuration. Entity configuration is done inside the AddTayra() options lambda. For production, register a persistent key store (PostgreSQL, Vault, etc.) which overrides the default in-memory store.

What AddTayra() Registers

A single call to AddTayra() registers the following services:

ServicePurpose
ITayraPrimary user-facing API — encryption, decryption, crypto-shredding, key rotation, blind index queries
IKeyStoreKey persistence (default: InMemoryKeyStore for development)

ITayra is the single entry point for all data protection operations. Resolve it from the container or use TayraHost.Create() for non-DI scenarios.

Key stores are the intended extension point — use UsePostgreSqlKeyStore(), UseVaultKeyStore(), or other key store builders to swap the default.

Registration Example

cs
var fullServices = new ServiceCollection();
fullServices.AddTayra(opts =>
{
    opts.LicenseKey = licenseKey;

    // How long encryption keys are cached in memory (default: 5 minutes)
    opts.KeyCacheDuration = TimeSpan.FromMinutes(10);

    // AES key size — 128, 192, or 256 bits (default: 256)
    opts.KeySizeInBits = 256;
});
anchor

Service Lifetimes

Every Tayra service is registered as a Singleton:

  • PersonalDataMetadataCache uses a ConcurrentDictionary to cache type metadata. It is thread-safe and never changes once built.
  • DefaultCryptoEngine wraps a MemoryCache for encryption keys. The cache respects the KeyCacheDuration option.
  • DefaultFieldEncrypter is stateless apart from its injected dependencies.

Singleton Key Store Requirement

Your IKeyStore implementation must also be thread-safe. All built-in key stores (InMemory, PostgreSql, Vault, AzureKeyVault, AwsKms) are registered as singletons and are thread-safe.

Chaining with Key Stores

AddTayra() defaults to the built-in InMemoryKeyStore, which is suitable for development and testing. For production, chain a key store registration from the returned TayraBuilder:

csharp
services.AddTayra(opts => opts.LicenseKey = licenseKey);
// Uses InMemoryKeyStore by default (keys lost on restart)

// Local development — persistent keys across restarts
services.AddTayra(opts => opts.LicenseKey = licenseKey)
    .UsePostgreSqlKeyStore(connectionString);

// Production — use a secrets manager
services.AddTayra(opts => opts.LicenseKey = licenseKey)
    .UseVaultKeyStore(options => { ... });

Fluent Entity Configuration

Call Entity<T>() inside the AddTayra() options lambda to configure entity types as an alternative to attributes. You can define data subject IDs, personal data fields, and replacement values entirely in code:

csharp
services.AddTayra(opts =>
{
    opts.LicenseKey = "...";
    opts.Entity<Customer>(e =>
    {
        e.DataSubjectId(c => c.Id).WithPrefix("cust-");
        e.PersonalData(c => c.Name);
        e.PersonalData(c => c.Email).WithMaskValue("[removed]");
    });
});

Blind index services are registered automatically by AddTayra() when [BlindIndex] attributes or fluent .BlindIndex() configurations are present.

TIP

See Fluent API for the complete builder reference.

Non-DI Usage

If your application doesn't use dependency injection, TayraHost.Create provides the same configuration experience. The simple form uses the in-memory key store:

cs
// Simple — in-memory key store, no builder needed
using var simpleTayra = TayraHost.Create(opts =>
{
    opts.LicenseKey = licenseKey;
});

await simpleTayra.EncryptAsync(new FluentCustomer { CustomerId = "non-di-001", Name = "Test", Email = "test@example.com" });
anchor

For key stores, compliance, or other configuration, use the builder overload — it supports the same extension methods as the DI path:

cs
// With builder — same extension methods as the DI path
using var builderTayra = TayraHost.Create(
    opts => opts.LicenseKey = licenseKey,
    builder =>
    {
        builder.UseSqliteKeyStore();
        builder.AddCompliance(complianceOpts =>
        {
            complianceOpts.AddEntityType<FluentCustomer>();
        });
    });

await builderTayra.EncryptAsync(new FluentCustomer { CustomerId = "non-di-002", Name = "Builder Test", Email = "builder@example.com" });
anchor

The builder overload internally creates a service collection, applies the same AddTayra() + extension method chain, and resolves ITayra. You get the same wiring — just without exposing the DI container.

See Also

  • Fluent API -- Complete builder reference for entity configuration
  • Options -- Configure cache duration, key size, and other settings
  • Licensing -- Production license key setup
  • Getting Started -- End-to-end tutorial