Skip to content

Commit 67d42fa

Browse files
authored
Updated test cases and removed samples (#7)
***NO_CI***
1 parent 712c44c commit 67d42fa

28 files changed

+132
-596
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Provides Dependency Injection (DI) for Inversion of Control (IoC) between classe
1818

1919
[Dependency Injection Sample](https://github.com/nanoframework/Samples/tree/main/samples/DependencyInjection)
2020

21+
[Dependency Injection Unit Tests](https://github.com/nanoframework/nanoFramework.DependencyInjection/tree/main/tests)
22+
2123
## Dependency Injection Container
2224

2325
A Dependency Injection (DI) Container provides functionality and automates many of the tasks involved in Object Composition, Interception, and Lifetime Management. It's an engine that resolves and manages object graphs. These DI Containers depend on the static information compiled into all classes. Then using reflection they can analyze the requested class and figure out which Dependencies are required.
@@ -39,6 +41,8 @@ Creating a dependency injection container required three basic components.
3941

4042
Define an object composition to create and couple.
4143

44+
Note: You can not currently define your objects as 'struct' or include array type parameters (ie. byte[] bytes) as constructor parameters. Doing so will create a null execption when trying to activate object.
45+
4246
```csharp
4347
public class RootObject
4448
{

nanoFramework.DependencyInjection.nuspec

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
</dependencies>
2323
</metadata>
2424
<files>
25-
<file src="WebSockets.Server\bin\Release\nanoFramework.DependencyInjection.dll" target="lib\nanoFramework.DependencyInjection.dll" />
26-
<file src="WebSockets.Server\bin\Release\nanoFramework.DependencyInjection.pdb" target="lib\nanoFramework.DependencyInjection.pdb" />
27-
<file src="WebSockets.Server\bin\Release\nanoFramework.DependencyInjection.pdbx" target="lib\nanoFramework.DependencyInjection.pdbx" />
28-
<file src="WebSockets.Server\bin\Release\nanoFramework.DependencyInjection.pe" target="lib\nanoFramework.DependencyInjection.pe" />
29-
<file src="WebSockets.Server\bin\Release\nanoFramework.DependencyInjection.xml" target="lib\nanoFramework.DependencyInjection.xml" />
25+
<file src="nanoFramework.DependencyInjection\bin\Release\nanoFramework.DependencyInjection.dll" target="lib\nanoFramework.DependencyInjection.dll" />
26+
<file src="nanoFramework.DependencyInjection\bin\Release\nanoFramework.DependencyInjection.pdb" target="lib\nanoFramework.DependencyInjection.pdb" />
27+
<file src="nanoFramework.DependencyInjection\bin\Release\nanoFramework.DependencyInjection.pdbx" target="lib\nanoFramework.DependencyInjection.pdbx" />
28+
<file src="nanoFramework.DependencyInjection\bin\Release\nanoFramework.DependencyInjection.pe" target="lib\nanoFramework.DependencyInjection.pe" />
29+
<file src="nanoFramework.DependencyInjection\bin\Release\nanoFramework.DependencyInjection.xml" target="lib\nanoFramework.DependencyInjection.xml" />
3030
<file src="assets\readme.txt" target="" />
3131
<file src="README.md" target="docs\" />
3232
<file src="assets\nf-logo.png" target="images\" />

nanoFramework.DependencyInjection/DependencyInjection/ActivatorUtilities.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static object CreateInstance(IServiceProvider provider, Type instanceType
5656
/// <param name="provider">The service provider.</param>
5757
/// <param name="type">The type of the service.</param>
5858
/// <returns>The resolved service or created instance.</returns>
59-
/// /// <exception cref="InvalidOperationException">Unable to resolve a service while attempting to activate a constructor.</exception>
59+
/// <exception cref="InvalidOperationException">Unable to resolve a service while attempting to activate a constructor.</exception>
6060
public static object GetServiceOrCreateInstance(IServiceProvider provider, Type type)
6161
{
6262
return provider.GetService(type) ?? CreateInstance(provider, type);
@@ -88,7 +88,7 @@ public int Match(object[] givenParameters)
8888
for (int applyIndex = applyIndexStart; !givenMatched && applyIndex != _parameters.Length; ++applyIndex)
8989
{
9090
if (_parameterValues[applyIndex] == null
91-
&& _parameters[applyIndex].ParameterType.Equals(givenType)) //TODO: Type.IsAssignableFrom?
91+
&& _parameters[applyIndex].ParameterType.Equals(givenType))
9292
{
9393
givenMatched = true;
9494
_parameterValues[applyIndex] = givenParameters[givenIndex];

nanoFramework.DependencyInjection/DependencyInjection/ServiceCollection.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ namespace nanoFramework.DependencyInjection
1212
/// </summary>
1313
public class ServiceCollection : IServiceCollection
1414
{
15-
// TODO: Scaleback locking? Count? GetEnumerator()?
1615
private static readonly object _syncLock = new object();
1716
private readonly ArrayList _descriptors = new ArrayList();
1817

nanoFramework.DependencyInjection/DependencyInjection/ServiceCollectionContainerBuilderExtensions.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
// See LICENSE file in the project root for full license information.
44
//
55

6-
using System;
7-
86
namespace nanoFramework.DependencyInjection
97
{
108
/// <summary>
@@ -31,16 +29,6 @@ public static ServiceProvider BuildServiceProvider(this IServiceCollection servi
3129
/// <returns>The <see cref="ServiceProvider"/>.</returns>
3230
public static ServiceProvider BuildServiceProvider(this IServiceCollection services, ServiceProviderOptions options)
3331
{
34-
if (services == null)
35-
{
36-
throw new ArgumentNullException(nameof(services));
37-
}
38-
39-
if (options == null)
40-
{
41-
throw new ArgumentNullException(nameof(options));
42-
}
43-
4432
return new ServiceProvider(services, options);
4533
}
4634
}

nanoFramework.DependencyInjection/DependencyInjection/ServiceCollectionServiceExtensions.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ public static void TryAdd(this IServiceCollection collection, ServiceDescriptor
167167
/// Use <see cref="TryAddEnumerable(IServiceCollection, ServiceDescriptor)"/> when registering a service implementation of a
168168
/// service type that
169169
/// supports multiple registrations of the same service type. Using
170-
/// <see cref="Add(ServiceDescriptor)"/> is not idempotent and can add
170+
/// <see cref="IServiceCollection.Add(ServiceDescriptor)"/> is not idempotent and can add
171171
/// duplicate
172172
/// <see cref="ServiceDescriptor"/> instances if called twice. Using
173173
/// <see cref="TryAddEnumerable(IServiceCollection, ServiceDescriptor)"/> will prevent registration
@@ -223,7 +223,7 @@ public static void TryAddEnumerable(this IServiceCollection services, ServiceDes
223223
/// Use <see cref="TryAddEnumerable(IServiceCollection, ServiceDescriptor)"/> when registering a service
224224
/// implementation of a service type that
225225
/// supports multiple registrations of the same service type. Using
226-
/// <see cref="Add(ServiceDescriptor)"/> is not idempotent and can add
226+
/// <see cref="IServiceCollection.Add(ServiceDescriptor)"/> is not idempotent and can add
227227
/// duplicate
228228
/// <see cref="ServiceDescriptor"/> instances if called twice. Using
229229
/// <see cref="TryAddEnumerable(IServiceCollection, ServiceDescriptor)"/> will prevent registration
@@ -242,9 +242,9 @@ public static void TryAddEnumerable(this IServiceCollection services, IEnumerabl
242242
throw new ArgumentNullException();
243243
}
244244

245-
foreach (ServiceDescriptor d in descriptors)
245+
foreach (ServiceDescriptor descriptor in descriptors)
246246
{
247-
services.TryAddEnumerable(d);
247+
services.TryAddEnumerable(descriptor);
248248
}
249249
}
250250

nanoFramework.DependencyInjection/DependencyInjection/ServiceDescriptor.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ public ServiceDescriptor(Type serviceType, Type implementationType, ServiceLifet
2727
{
2828
if (serviceType == null)
2929
{
30-
throw new ArgumentNullException(nameof(serviceType));
30+
throw new ArgumentNullException();
3131
}
3232

3333
if (implementationType == null)
3434
{
35-
throw new ArgumentNullException(nameof(implementationType));
35+
throw new ArgumentNullException();
3636
}
3737

3838
if (implementationType.IsAbstract || implementationType.IsInterface)
@@ -55,12 +55,12 @@ public ServiceDescriptor(Type serviceType, object instance)
5555
{
5656
if (serviceType == null)
5757
{
58-
throw new ArgumentNullException(nameof(serviceType));
58+
throw new ArgumentNullException();
5959
}
6060

6161
if (instance == null)
6262
{
63-
throw new ArgumentNullException(nameof(instance));
63+
throw new ArgumentNullException();
6464
}
6565

6666
ImplementationInstance = instance;

nanoFramework.DependencyInjection/DependencyInjection/ServiceProvider.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ public sealed class ServiceProvider : IServiceProvider, IDisposable
1818

1919
internal ServiceProvider(IServiceCollection services, ServiceProviderOptions options)
2020
{
21+
if (services == null)
22+
{
23+
throw new ArgumentNullException();
24+
}
25+
26+
if (options == null)
27+
{
28+
throw new ArgumentNullException();
29+
}
30+
2131
_engine = GetEngine();
2232
_engine.Services = services;
2333
_engine.Services.Add(new ServiceDescriptor(typeof(IServiceProvider), this));

nanoFramework.DependencyInjection/DependencyInjection/ServiceProviderEngine.cs

Lines changed: 33 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ internal void DisposeServices()
3838
{
3939
foreach (ServiceDescriptor descriptor in Services)
4040
{
41-
if (descriptor.ServiceType != typeof(IServiceProvider))
41+
if (descriptor.ServiceType == typeof(IServiceProvider))
4242
{
43-
if (descriptor.ImplementationInstance is IDisposable instance)
44-
{
45-
instance.Dispose();
46-
}
43+
continue;
44+
}
45+
46+
if (descriptor.ImplementationInstance is IDisposable instance)
47+
{
48+
instance.Dispose();
4749
}
4850
}
4951
}
@@ -75,12 +77,12 @@ internal object[] GetService(Type[] serviceType)
7577
{
7678
if (serviceType == null)
7779
{
78-
throw new ArgumentNullException(nameof(serviceType));
80+
throw new ArgumentNullException();
7981
}
8082

8183
if (serviceType.Length == 0)
8284
{
83-
throw new ArgumentException(nameof(serviceType));
85+
throw new ArgumentException();
8486
}
8587

8688
// optimized for single item service type
@@ -179,11 +181,10 @@ private object Resolve(Type implementationType)
179181
{
180182
var parameterType = constructorParameters[index].ParameterType;
181183

182-
// TODO: I can't figure out a better way to bind primitives or create defaults. Any ideas are welcome?
183-
if (CanBindPrimitive(parameterType))
184+
if (TryBindToPrimitive(parameterType, out object defaultType))
184185
{
185186
types[index] = parameterType;
186-
parameters[index] = CreateDefaultPrimitive(parameterType);
187+
parameters[index] = defaultType;
187188
}
188189
else
189190
{
@@ -247,10 +248,30 @@ private ParameterInfo[] GetParameters(Type implementationType)
247248
}
248249

249250
/// <summary>
250-
/// Attempts to bind to a primitive.
251+
/// Try and bind to a primitive type.
251252
/// </summary>
252-
private static bool CanBindPrimitive(Type type)
253+
private static bool TryBindToPrimitive(Type type, out object defaultType)
253254
{
255+
defaultType = null;
256+
257+
// This list dosn't match the binding list below because
258+
// we only check for items we know are not null by default
259+
if (type == typeof(object)) defaultType = default;
260+
if (type == typeof(int)) defaultType = default(int);
261+
if (type == typeof(uint)) defaultType = default(uint);
262+
if (type == typeof(bool)) defaultType = default(bool);
263+
if (type == typeof(char)) defaultType = default(char);
264+
if (type == typeof(byte)) defaultType = default(byte);
265+
if (type == typeof(sbyte)) defaultType = default(sbyte);
266+
if (type == typeof(short)) defaultType = default(short);
267+
if (type == typeof(ushort)) defaultType = default(ushort);
268+
if (type == typeof(long)) defaultType = default(long);
269+
if (type == typeof(ulong)) defaultType = default(ulong);
270+
if (type == typeof(double)) defaultType = default(double);
271+
if (type == typeof(Guid)) defaultType = default(Guid);
272+
if (type == typeof(DateTime)) defaultType = default(DateTime);
273+
if (type == typeof(TimeSpan)) defaultType = default(TimeSpan);
274+
254275
return type == typeof(object)
255276
|| type == typeof(string)
256277
|| type == typeof(int)
@@ -264,66 +285,12 @@ private static bool CanBindPrimitive(Type type)
264285
|| type == typeof(long)
265286
|| type == typeof(ulong)
266287
|| type == typeof(double)
267-
|| type == typeof(object[])
268-
|| type == typeof(string[])
269-
|| type == typeof(int[])
270-
|| type == typeof(uint[])
271-
|| type == typeof(bool[])
272-
|| type == typeof(char[])
273-
|| type == typeof(byte[])
274-
|| type == typeof(sbyte[])
275-
|| type == typeof(short[])
276-
|| type == typeof(ushort[])
277-
|| type == typeof(long[])
278-
|| type == typeof(ulong[])
279-
|| type == typeof(double[])
280288
|| type == typeof(Guid)
281289
|| type == typeof(DateTime)
282290
|| type == typeof(TimeSpan)
283291
|| type == typeof(Enum)
284292
|| type == typeof(Array)
285293
|| type == typeof(ArrayList);
286294
}
287-
288-
/// <summary>
289-
/// Bind to a primitive using default values.
290-
/// </summary>
291-
private static object CreateDefaultPrimitive(Type type)
292-
{
293-
if (type == typeof(object)) return default;
294-
if (type == typeof(string)) return default(string);
295-
if (type == typeof(int)) return default(int);
296-
if (type == typeof(uint)) return default(uint);
297-
if (type == typeof(bool)) return default(bool);
298-
if (type == typeof(char)) return default(char);
299-
if (type == typeof(byte)) return default(byte);
300-
if (type == typeof(sbyte)) return default(sbyte);
301-
if (type == typeof(short)) return default(short);
302-
if (type == typeof(ushort)) return default(ushort);
303-
if (type == typeof(long)) return default(long);
304-
if (type == typeof(ulong)) return default(ulong);
305-
if (type == typeof(double)) return default(double);
306-
if (type == typeof(object[])) return default(object[]);
307-
if (type == typeof(string[])) return default(string[]);
308-
if (type == typeof(int[])) return default(int[]);
309-
if (type == typeof(uint[])) return default(uint[]);
310-
if (type == typeof(bool[])) return default(bool[]);
311-
if (type == typeof(char[])) return default(char[]);
312-
if (type == typeof(byte[])) return default(byte[]);
313-
if (type == typeof(sbyte[])) return default(sbyte[]);
314-
if (type == typeof(short[])) return default(short[]);
315-
if (type == typeof(ushort[])) return default(ushort[]);
316-
if (type == typeof(long[])) return default(long[]);
317-
if (type == typeof(ulong[])) return default(ulong[]);
318-
if (type == typeof(double[])) return default(double[]);
319-
if (type == typeof(Guid)) return default(Guid);
320-
if (type == typeof(DateTime)) return default(DateTime);
321-
if (type == typeof(TimeSpan)) return default(TimeSpan);
322-
if (type == typeof(Enum)) return default(Enum);
323-
if (type == typeof(Array)) return default(Array);
324-
if (type == typeof(ArrayList)) return default(ArrayList);
325-
326-
return null;
327-
}
328295
}
329296
}

nanoFramework.DependencyInjection/DependencyInjection/ServiceProviderServiceExtensions.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ public static object[] GetServices(this IServiceProvider provider, Type[] servic
3434
{
3535
if (provider == null)
3636
{
37-
throw new ArgumentNullException(nameof(provider));
37+
throw new ArgumentNullException();
3838
}
3939

4040
if (serviceType == null)
4141
{
42-
throw new ArgumentNullException(nameof(serviceType));
42+
throw new ArgumentNullException();
4343
}
4444

4545
return provider.GetService(serviceType);
@@ -57,12 +57,12 @@ public static object GetRequiredService(this IServiceProvider provider, Type ser
5757
{
5858
if (provider == null)
5959
{
60-
throw new ArgumentNullException(nameof(provider));
60+
throw new ArgumentNullException();
6161
}
6262

6363
if (serviceType == null)
6464
{
65-
throw new ArgumentNullException(nameof(serviceType));
65+
throw new ArgumentNullException();
6666
}
6767

6868
object service = provider.GetService(serviceType);

0 commit comments

Comments
 (0)