Skip to content

Commit 76ba99e

Browse files
author
LoneWandererProductions
committed
refine injector
1 parent 2b3917d commit 76ba99e

2 files changed

Lines changed: 65 additions & 28 deletions

File tree

Core.Inject/CoreInjector.cs

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
using System;
1010
using System.Collections.Generic;
11+
using System.Linq;
1112

1213
namespace Core.Inject
1314
{
@@ -117,6 +118,23 @@ public void RegisterInstance<TService>(TService instance)
117118
};
118119
}
119120

121+
/// <summary>
122+
/// Registers the transient.
123+
/// </summary>
124+
/// <param name="serviceType">Type of the service.</param>
125+
/// <param name="implementationType">Type of the implementation.</param>
126+
/// <exception cref="System.InvalidOperationException">Service {serviceType.Name} is already registered.</exception>
127+
public void RegisterTransient(Type serviceType, Type implementationType)
128+
{
129+
if (_registrations.ContainsKey(serviceType))
130+
{
131+
throw new InvalidOperationException($"Service {serviceType.Name} is already registered.");
132+
}
133+
134+
// We store a factory that calls our new CreateInstance method
135+
_registrations[serviceType] = () => CreateInstance(implementationType);
136+
}
137+
120138
/// <summary>
121139
/// Resolves an instance of the requested service type.
122140
/// If a scope is active, the service will be resolved within that scope.
@@ -133,6 +151,26 @@ public TService Resolve<TService>()
133151
return (TService)Resolve(typeof(TService));
134152
}
135153

154+
/// <summary>
155+
/// Starts a new dependency scope.
156+
/// Scoped services can be resolved within this scope.
157+
/// </summary>
158+
public void BeginScope()
159+
{
160+
_currentScope = new SimpleScope();
161+
}
162+
163+
/// <summary>
164+
/// Ends the current dependency scope.
165+
/// Scoped services will no longer be available after this point.
166+
/// </summary>
167+
public void EndScope()
168+
{
169+
_currentScope?.Dispose();
170+
_currentScope = null;
171+
}
172+
173+
136174
/// <summary>
137175
/// Resolves a service by its type.
138176
/// </summary>
@@ -151,22 +189,32 @@ private object Resolve(Type serviceType)
151189
}
152190

153191
/// <summary>
154-
/// Starts a new dependency scope.
155-
/// Scoped services can be resolved within this scope.
192+
/// Creates the instance.
156193
/// </summary>
157-
public void BeginScope()
194+
/// <param name="implementationType">Type of the implementation.</param>
195+
/// <returns>The created instance.</returns>
196+
private object CreateInstance(Type implementationType)
158197
{
159-
_currentScope = new SimpleScope();
160-
}
198+
// Find the best constructor (for now, we'll just take the first one)
199+
var constructor = implementationType.GetConstructors()
200+
.OrderByDescending(c => c.GetParameters().Length) // Pick the one with the most params
201+
.First();
161202

162-
/// <summary>
163-
/// Ends the current dependency scope.
164-
/// Scoped services will no longer be available after this point.
165-
/// </summary>
166-
public void EndScope()
167-
{
168-
_currentScope?.Dispose();
169-
_currentScope = null;
203+
var parameters = constructor.GetParameters();
204+
205+
if (parameters.Length == 0)
206+
{
207+
return Activator.CreateInstance(implementationType);
208+
}
209+
210+
// Recursively resolve each dependency found in the constructor
211+
var parameterInstances = new List<object>();
212+
foreach (var parameter in parameters)
213+
{
214+
parameterInstances.Add(Resolve(parameter.ParameterType));
215+
}
216+
217+
return constructor.Invoke(parameterInstances.ToArray());
170218
}
171219
}
172220
}

Core.Inject/CoreInjectorExtensions.cs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,12 @@ public static void RegisterFromAssembly(this CoreInjector injector, Assembly ass
3333
.Where(t => t.IsClass && !t.IsAbstract)
3434
.SelectMany(t => t.GetInterfaces(), (t, i) => new { Implementation = t, Interface = i });
3535

36-
foreach (var type in types.Where(type => !injector.IsServiceRegistered(type.Interface)))
36+
foreach (var type in types)
3737
{
38-
// Try to register the service
39-
try
38+
if (!injector.IsServiceRegistered(type.Interface))
4039
{
41-
var method = typeof(CoreInjector)
42-
.GetMethod(CoreInjectResource.MethodRegisterTransient,
43-
BindingFlags.Public | BindingFlags.Instance)
44-
?.MakeGenericMethod(type.Interface, type.Implementation);
45-
46-
method?.Invoke(injector, null);
47-
}
48-
catch (InvalidOperationException ex)
49-
{
50-
// Log and handle any errors if needed, this should not happen anymore
51-
throw new InvalidOperationException(string.Format(CoreInjectResource.ErrorRegisteringService,
52-
type.Interface.Name, ex.Message));
40+
// Now we call the non-generic version directly!
41+
injector.RegisterTransient(type.Interface, type.Implementation);
5342
}
5443
}
5544
}

0 commit comments

Comments
 (0)