Compare commits
2 Commits
v0.0.1.6-a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65f624a355 | ||
|
|
66e7fcc798 |
@@ -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.
|
||||
@@ -153,26 +153,42 @@ public class ServiceContainer {
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <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];
|
||||
|
||||
// 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) {
|
||||
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);
|
||||
/// <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 method.Invoke(this, null)!;
|
||||
return GetService(serviceType, args);
|
||||
} catch {
|
||||
return null!;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,13 +240,13 @@ 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.");
|
||||
|
||||
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
|
||||
|
||||
@@ -8,20 +8,28 @@ 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; }
|
||||
|
||||
/// <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})";
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>0.0.1.6-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>
|
||||
|
||||
Reference in New Issue
Block a user