Rystem.DependencyInjection
9.0.0
dotnet add package Rystem.DependencyInjection --version 9.0.0
NuGet\Install-Package Rystem.DependencyInjection -Version 9.0.0
<PackageReference Include="Rystem.DependencyInjection" Version="9.0.0" />
paket add Rystem.DependencyInjection --version 9.0.0
#r "nuget: Rystem.DependencyInjection, 9.0.0"
// Install Rystem.DependencyInjection as a Cake Addin #addin nuget:?package=Rystem.DependencyInjection&version=9.0.0 // Install Rystem.DependencyInjection as a Cake Tool #tool nuget:?package=Rystem.DependencyInjection&version=9.0.0
What is Rystem?
Get Started
Dependency injection extensions
Warm up
When you use the DI pattern in your .Net application you could need a warm up after the build of your services. And with Rystem you can simply do it.
builder.Services.AddWarmUp(() => somethingToDo());
and after the build use the warm up
var app = builder.Build();
await app.Services.WarmUpAsync();
Population service
You can use the population service to create a list of random value of a specific Type. An example from unit test explains how to use the service.
IServiceCollection services = new ServiceCollection();
services.AddPopulationService();
var serviceProvider = services.BuildServiceProvider().CreateScope().ServiceProvider;
var populatedModel = serviceProvider.GetService<IPopulation<PopulationModelTest>>();
IPopulation<PopulationModelTest> allPrepopulation = populatedModel!
.Setup()
.WithPattern(x => x.J!.First().A, "[a-z]{4,5}")
.WithPattern(x => x.Y!.First().Value.A, "[a-z]{4,5}")
.WithImplementation(x => x.I, typeof(MyInnerInterfaceImplementation))
.WithPattern(x => x.I!.A!, "[a-z]{4,5}")
.WithPattern(x => x.II!.A!, "[a-z]{4,5}")
.WithImplementation<IInnerInterface, MyInnerInterfaceImplementation>(x => x.I!);
var all = allPrepopulation.Populate();
Abstract factory
You can use this abstract factory solution when you need to setup more than one service of the same kind and you need to distinguish them by a name.
I have an interface
public interface IMyService
{
string GetName();
}
Some options for every service
public class SingletonOption
{
public string ServiceName { get; set; }
}
public class TransientOption
{
public string ServiceName { get; set; }
}
public class ScopedOption
{
public string ServiceName { get; set; }
}
with built options which is a IServiceOptions, a options class that ends up with another class. Used for example when you have to add a settings like a connection string but you want to use a service like a client that uses that connection string.
public class BuiltScopedOptions : IServiceOptions<ScopedOption>
{
public string ServiceName { get; set; }
public Task<Func<ScopedOption>> BuildAsync()
{
return Task.FromResult(() => new ScopedOption
{
ServiceName = ServiceName
});
}
}
And six different services
public class SingletonService : IMyService, IServiceWithOptions<SingletonOption>
{
public SingletonOption Options { get; set; }
public string Id { get; } = Guid.NewGuid().ToString();
public string GetName()
{
return $"{Options.ServiceName} with id {Id}";
}
}
public class TransientService : IMyService, IServiceWithOptions<TransientOption>
{
public TransientOption Options { get; set; }
public string Id { get; } = Guid.NewGuid().ToString();
public string GetName()
{
return $"{Options.ServiceName} with id {Id}";
}
}
public class ScopedService : IMyService, IServiceWithOptions<ScopedOption>
{
public ScopedOption Options { get; set; }
public string Id { get; } = Guid.NewGuid().ToString();
public string GetName()
{
return $"{Options.ServiceName} with id {Id}";
}
}
public class ScopedService2 : IMyService, IServiceWithOptions<ScopedOption>
{
public ScopedOption Options { get; set; }
public string Id { get; } = Guid.NewGuid().ToString();
public string GetName()
{
return $"{Options.ServiceName} with id {Id}";
}
}
public class ScopedService3 : IMyService, IServiceWithOptions<ScopedOption>
{
public ScopedOption Options { get; set; }
public string Id { get; } = Guid.NewGuid().ToString();
public string GetName()
{
return $"{Options.ServiceName} with id {Id}";
}
}
public class ScopedService4 : IMyService, IServiceWithOptions<ScopedOption>
{
public ScopedOption Options { get; set; }
public string Id { get; } = Guid.NewGuid().ToString();
public string GetName()
{
return $"{Options.ServiceName} with id {Id}";
}
}
I can setup them in this way
var services = new ServiceCollection();
services.AddFactory<IMyService, SingletonService, SingletonOption>(x =>
{
x.ServiceName = "singleton";
},
"singleton",
ServiceLifetime.Singleton);
services.AddFactory<IMyService, TransientService, TransientOption>(x =>
{
x.ServiceName = "transient";
},
"transient",
ServiceLifetime.Transient);
services.AddFactory<IMyService, ScopedService, ScopedOption>(x =>
{
x.ServiceName = "scoped";
},
"scoped",
ServiceLifetime.Scoped);
services.AddFactory<IMyService, ScopedService2, ScopedOption>(x =>
{
x.ServiceName = "scoped2";
},
"scoped2",
ServiceLifetime.Scoped);
await services.AddFactoryAsync<IMyService, ScopedService3, BuiltScopedOptions, ScopedOption>(
x =>
{
x.ServiceName = "scoped3";
},
"scoped3"
);
await services.AddFactoryAsync<IMyService, ScopedService3, BuiltScopedOptions, ScopedOption>(
x =>
{
x.ServiceName = "scoped3_2";
},
"scoped3_2"
);
await services.AddFactoryAsync<IMyService, ScopedService4, BuiltScopedOptions, ScopedOption>(
x =>
{
x.ServiceName = "scoped4";
},
"scoped4"
);
and use them in this way
var serviceProvider = services.BuildServiceProvider().CreateScope().ServiceProvider;
var factory = serviceProvider.GetService<IFactory<IMyService>>()!;
var factory2 = serviceProvider.GetService<IFactory<IMyService>>()!;
var singletonFromFactory = factory.Create("singleton").Id;
var singletonFromFactory2 = factory2.Create("singleton").Id;
var transientFromFactory = factory.Create("transient").Id;
var transientFromFactory2 = factory2.Create("transient").Id;
var scopedFromFactory = factory.Create("scoped").Id;
var scopedFromFactory2 = factory2.Create("scoped").Id;
var scoped2FromFactory = factory.Create("scoped2").Id;
var scoped2FromFactory2 = factory2.Create("scoped2").Id;
var scoped3FromFactory = factory.Create("scoped3").Id;
var scoped3FromFactory2 = factory2.Create("scoped3").Id;
var scoped3_2FromFactory = factory.Create("scoped3_2").Id;
var scoped3_2FromFactory2 = factory2.Create("scoped3_2").Id;
var scoped4FromFactory = factory.Create("scoped4").Id;
var scoped4FromFactory2 = factory2.Create("scoped4").Id;
Assert.Equal(singletonFromFactory, singletonFromFactory2);
Assert.NotEqual(transientFromFactory, transientFromFactory2);
Assert.Equal(scopedFromFactory, scopedFromFactory2);
Assert.Equal(scoped2FromFactory, scoped2FromFactory2);
Assert.NotEqual(scoped3FromFactory, scoped3FromFactory2);
Assert.NotEqual(scoped3_2FromFactory, scoped3_2FromFactory2);
Assert.NotEqual(scoped4FromFactory, scoped4FromFactory2);
Decorator
You may add a decoration for your services, based on the abstract factory integration. The decorator service replaces the previous version and receives it during the injection.
Setup
services
.AddService<ITestWithoutFactoryService, TestWithoutFactoryService>(lifetime);
services
.AddDecoration<ITestWithoutFactoryService, TestWithoutFactoryServiceDecorator>(null, lifetime);
Usage
var decorator = provider.GetRequiredService<ITestWithoutFactoryService>();
var previousService = provider.GetRequiredService<IDecoratedService<ITestWithoutFactoryService>>();
In decorator you may find the previousService in the method SetDecoratedService which runs in injection
public class TestWithoutFactoryServiceDecorator : ITestWithoutFactoryService, IDecoratorService<ITestWithoutFactoryService>
{
public string Id { get; } = Guid.NewGuid().ToString();
public ITestWithoutFactoryService Test { get; private set; }
public void SetDecoratedService(ITestWithoutFactoryService service)
{
Test = service;
}
public void SetFactoryName(string name)
{
return;
}
}
Decorator with Abstract Factory integration
You may add a decoration only for one service of your factory integration.
Setup
services.AddFactory<ITestService, TestService, TestOptions>(x =>
{
x.ClassicName = classicName;
},
factoryName,
lifetime);
services
.AddDecoration<ITestService, DecoratorTestService>(factoryName, lifetime);
Usage
var decoratorFactory = provider.GetRequiredService<IFactory<ITestService>>();
var decorator = decoratorFactory.Create(factoryName);
var previousService = decoratorFactory.CreateWithoutDecoration(factoryName);
Factory Fallback
You may add a fallback for your factory integration. The fallback service is called when the factory service key is not found.
services.AddFactoryFallback<TService, TFactoryFallback>();
where TFactoryFallback is class and an IFactoryFallback<TService>
You may add a fallback with an action fallback too.
services.AddActionAsFallbackWithServiceProvider<TService>(Func<FallbackBuilderForServiceProvider, TService> fallbackBuilder);
Scan dependency injection
You may scan your assemblies in search of types you need to add to dependency injection. For instance I have an interface IAnything and I need to add all classes which implements it.
public interface IAnything
{
}
internal class ScanModels : IAnything
{
}
and in service collection I can add it.
serviceCollection
.Scan<IAnything>(ServiceLifetime.Scoped, typeof(IAnything).Assembly);
I can add to my class the interface IScannable of T to scan automatically. For instance.
public interface IAnything
{
}
internal class ScanModels : IAnything, IScannable<IAnything>
{
}
and in service collection I could add it in this way
serviceCollection
.Scan(ServiceLifetime.Scoped, typeof(IAnything).Assembly);
Furthermore with ISingletonScannable, IScopedScannable and ITransientScannable I can override the service lifetime. For instance.
public interface IAnything
{
}
internal class ScanModels : IAnything, IScannable<IAnything>, ISingletonScannable
{
}
serviceCollection
.Scan(ServiceLifetime.Scoped, typeof(IAnything).Assembly);
ScanModels will be installed as a Singleton service, overwriting the service lifetime from Scan method.
You also automatically use different assembly sources.
serviceCollection
.ScanDependencyContext(ServiceLifetime.Scoped);
or
serviceCollection
.ScanCallingAssembly(ServiceLifetime.Scoped);
or
serviceCollection
.ScanCurrentDomain(ServiceLifetime.Scoped);
or
serviceCollection
.ScanEntryAssembly(ServiceLifetime.Scoped);
or
serviceCollection
.ScanExecutingAssembly(ServiceLifetime.Scoped);
or
serviceCollection
.ScanFromType<T>(ServiceLifetime.Scoped);
or
serviceCollection
.ScanFromTypes<T1, T2>(ServiceLifetime.Scoped);
Finally with ScanWithReferences you may call all the assemblies you want plus all referenced assemblies by them.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. |
-
net9.0
- Microsoft.Extensions.DependencyInjection (>= 9.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
- Microsoft.Extensions.DependencyModel (>= 9.0.0)
- Rystem (>= 9.0.0)
NuGet packages (8)
Showing the top 5 NuGet packages that depend on Rystem.DependencyInjection:
Package | Downloads |
---|---|
Rystem.RepositoryFramework.Abstractions
Rystem.RepositoryFramework allows you to use correctly concepts like repository pattern, CQRS and DDD. You have interfaces for your domains, auto-generated api, auto-generated HttpClient to simplify connection "api to front-end", a functionality for auto-population in memory of your models, a functionality to simulate exceptions and waiting time from external sources to improve your implementation/business test and load test. |
|
Rystem.Api
Rystem.Api helps you to integrate Api Server and Automated Client for Aspect-Oriented programming. |
|
Rystem.Content.Abstractions
Rystem.Content helps you to integrate with azure services or to create an abstraction layer among your infrastructure and your business. |
|
Rystem.Authentication.Social
Rystem.Authentication.Social helps you to integrate with new .Net Identity system and social logins. |
|
Rystem.Concurrency
Rystem. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
9.0.0 | 12,448 | 11/16/2024 |
9.0.0-rc.1 | 227 | 10/18/2024 |
6.2.0 | 219,453 | 10/9/2024 |
6.1.2 | 82 | 10/9/2024 |
6.1.1 | 380 | 10/9/2024 |
6.1.0 | 48,254 | 9/29/2024 |
6.0.24 | 628 | 9/11/2024 |
6.0.23 | 340,535 | 7/18/2024 |
6.0.22 | 83 | 7/18/2024 |
6.0.21 | 474 | 6/18/2024 |
6.0.20 | 728,093 | 6/16/2024 |
6.0.19 | 30,921 | 6/14/2024 |
6.0.18 | 440 | 6/14/2024 |
6.0.17 | 452 | 6/14/2024 |
6.0.16 | 50,315 | 6/10/2024 |
6.0.15 | 442 | 6/9/2024 |
6.0.14 | 94,778 | 5/24/2024 |
6.0.13 | 449 | 5/23/2024 |
6.0.12 | 366 | 5/23/2024 |
6.0.11 | 462 | 5/20/2024 |
6.0.9 | 481 | 5/19/2024 |
6.0.7 | 429 | 5/18/2024 |
6.0.6 | 417 | 5/10/2024 |
6.0.5 | 362 | 5/10/2024 |
6.0.4 | 550,443 | 4/3/2024 |
6.0.3 | 1,691 | 3/25/2024 |
6.0.2 | 380,397 | 3/11/2024 |
6.0.1 | 51,106 | 3/8/2024 |
6.0.0 | 1,171,774 | 11/21/2023 |
6.0.0-rc.6 | 187 | 10/25/2023 |
6.0.0-rc.5 | 123 | 10/25/2023 |
6.0.0-rc.4 | 104 | 10/23/2023 |
6.0.0-rc.3 | 99 | 10/19/2023 |
6.0.0-rc.2 | 173 | 10/18/2023 |
6.0.0-rc.1 | 194 | 10/16/2023 |
5.0.20 | 640,227 | 9/25/2023 |
5.0.19 | 2,861 | 9/10/2023 |
5.0.18 | 2,136 | 9/6/2023 |
5.0.17 | 2,019 | 9/6/2023 |
5.0.16 | 2,057 | 9/5/2023 |
5.0.15 | 2,025 | 9/5/2023 |
5.0.14 | 2,033 | 9/5/2023 |
5.0.13 | 2,136 | 9/1/2023 |
5.0.12 | 1,985 | 8/31/2023 |
5.0.11 | 1,993 | 8/30/2023 |
5.0.10 | 2,038 | 8/29/2023 |
5.0.9 | 2,073 | 8/24/2023 |
5.0.8 | 2,081 | 8/24/2023 |
5.0.7 | 451,537 | 8/23/2023 |