Exposes GetService(Type, obiect[]? args) and it's safer variant TryGetService() to enable consumers to request a service without needing to do reflection work themselves.
All checks were successful
Nuget Pkg Build / build (push) Successful in 1m11s

bumps version to 0.0.1.8-alpha
This commit is contained in:
Samuele Lorefice
2025-10-01 19:03:53 +02:00
parent 66e7fcc798
commit 65f624a355
3 changed files with 28 additions and 10 deletions

View File

@@ -153,12 +153,17 @@ public class ServiceContainer {
});
return this;
}
// you can't call generic methods with an unknown type at compile time
// 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, object[]? args = null) {
/// <summary>
/// Resolves and returns an instance of the requested service type.
/// </summary>
/// <param name="serviceType">Type of the service that's being requested</param>
/// <param name="args">arguments to pass to the constructor of the service</param>
/// <remarks> you can't call generic methods with an unknown type at compile time
/// 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.</remarks>
/// <returns>An object that is the instantiated service type</returns>
public object GetService(Type serviceType, object[]? args = null) {
List<Type> arguments = [serviceType];
if (args != null) arguments.AddRange(args.ToList().Select(a => a.GetType()));
@@ -170,11 +175,20 @@ public class ServiceContainer {
return method.Invoke(this, args)!;
}
private object? TryGetService(Type serviceType, object[]? args = null) {
/// <summary>
/// tries to resolve and return an instance of the requested service type. Returns null if it fails.
/// </summary>
/// <param name="serviceType">Type of the service that's being requested</param>
/// <param name="args">arguments to pass to the constructor of the service</param>
/// <remarks> you can't call generic methods with an unknown type at compile time
/// 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.</remarks>
/// <returns>An object that is the instantiated service type or null if not found</returns>
public object? TryGetService(Type serviceType, object[]? args = null) {
try {
return GetService(serviceType, args);
} catch {
return null!;
return null;
}
}
@@ -226,7 +240,7 @@ public class ServiceContainer {
singletons[descriptor.ServiceType] = newSingleton!;
return newSingleton;
}
private TInterface Instantiate<TInterface>(ServiceDescriptor descriptor, ConstructorInfo? ctor = null) {
if (ctor == null && descriptor.ImplementationType.GetConstructors().Length > 1)
throw new Exception($"Multiple constructors found for type {descriptor.ImplementationType}. Please provide a specific constructor.");

View File

@@ -25,6 +25,10 @@ public class ServiceDescriptor
/// </summary>
public List<object>? Arguments { get; init; }
/// <summary>
/// Returns a string with the specific type of service, its implementation, and its lifetime.
/// </summary>
/// <returns>{implementation Name} as {Service Name} ({Lifetime})</returns>
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.7-alpha</Version>
<Version>0.0.1.8-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>