Fixes #5 makes copy of the args list instead of stripping it away from the descriptor (preventing catastrophic problems). Bumps version
All checks were successful
Nuget Pkg Build / build (push) Successful in 1m7s

This commit is contained in:
Samuele Lorefice
2025-09-24 19:53:29 +02:00
parent c888da8045
commit 66e7fcc798
3 changed files with 21 additions and 15 deletions

View File

@@ -24,7 +24,7 @@ public class ServiceContainer {
/// <typeparam name="TService"></typeparam>
public List<TService> GetServices<TService>() where TService : class =>
descriptors.Where(d => d.ServiceType == typeof(TService))
.Select(d => (TService)GetService(d.ImplementationType)).ToList();
.Select(d => (TService)GetService(d.ImplementationType, d.Arguments?.ToArray())).ToList();
/// <summary>
/// Registers a singleton service with its implementation.
@@ -158,19 +158,21 @@ public class ServiceContainer {
// so we use reflection to call the generic GetService<T> method with the provided type
// Basically we build the method GetService<serviceType>() at runtime and then call it.
// "Classic black magic sorcery" in reflection.
private object GetService(Type serviceType) {
private object GetService(Type serviceType, object[]? args = null) {
List<Type> arguments = [serviceType];
if (args != null) arguments.AddRange(args.ToList().Select(a => a.GetType()));
var method = typeof(ServiceContainer)
.GetMethod(nameof(GetService))!
.MakeGenericMethod(serviceType);
return method.Invoke(this, null)!;
.MakeGenericMethod(arguments.ToArray());
return method.Invoke(this, args)!;
}
private object? TryGetService(Type serviceType) {
var method = typeof(ServiceContainer)
.GetMethod(nameof(GetService))!
.MakeGenericMethod(serviceType);
private object? TryGetService(Type serviceType, object[]? args = null) {
try {
return method.Invoke(this, null)!;
return GetService(serviceType, args);
} catch {
return null!;
}
@@ -230,7 +232,7 @@ public class ServiceContainer {
throw new Exception($"Multiple constructors found for type {descriptor.ImplementationType}. Please provide a specific constructor.");
List<ParameterInfo> par;
List<object> args = descriptor.Arguments ?? new List<object>();
List<object> args = descriptor.Arguments != null ? new List<object>(descriptor.Arguments) : new List<object>();
if (ctor == null)
par = descriptor.ImplementationType

View File

@@ -8,20 +8,24 @@ public class ServiceDescriptor
/// <summary>
/// Gets or sets the type of the service to be provided.
/// </summary>
public required Type ServiceType { get; set; }
public required Type ServiceType { get; init; }
/// <summary>
/// Gets or sets the concrete type that implements the service.
/// </summary>
public required Type ImplementationType { get; set; }
public required Type ImplementationType { get; init; }
/// <summary>
/// Gets or sets the lifetime of the service (e.g., Singleton or Transient).
/// </summary>
public required ServiceLifetime Lifetime { get; set; }
public required ServiceLifetime Lifetime { get; init; }
/// <summary>
/// Arguments to be passed to the constructor of the implementation type.
/// </summary>
public List<object>? Arguments { get; set; }
public List<object>? Arguments { get; init; }
public override string ToString() {
return $"{ImplementationType.Name} as {ServiceType.Name} ({Lifetime})";
}
}

View File

@@ -9,7 +9,7 @@
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.0.1.6-alpha</Version>
<Version>0.0.1.7-alpha</Version>
<Title>Syrette </Title>
<Authors>Lorefice Samuele</Authors>
<Description>Syrette is a minimalistic dependency injection library for C#. It aims to provide a simple and efficient way to achieve dependency injections in your applications without the overhead of larger frameworks.</Description>