├── assets
├── nf-logo.png
└── readme.txt
├── .editorconfig
├── nanoFramework.DependencyInjection
├── key.snk
├── packages.config
├── Microsoft
│ └── Extensions
│ │ └── DependencyInjection
│ │ ├── IServiceScope.cs
│ │ ├── IServiceProviderIsService.cs
│ │ ├── ServiceLifetime.cs
│ │ ├── ServiceProviderOptions.cs
│ │ ├── TypeExtensions.cs
│ │ ├── ServiceScope.cs
│ │ ├── ServiceCollectionContainerBuilderExtensions.cs
│ │ ├── ServiceProvider.cs
│ │ ├── IServiceCollection.cs
│ │ ├── ServiceCollection.cs
│ │ ├── ServiceProviderEngineScope.cs
│ │ ├── ServiceProviderServiceExtensions.cs
│ │ ├── ActivatorUtilities.cs
│ │ ├── ServiceCollectionServiceExtensions.cs
│ │ ├── ServiceDescriptor.cs
│ │ └── ServiceProviderEngine.cs
├── packages.lock.json
├── Properties
│ └── AssemblyInfo.cs
├── System
│ ├── IServiceProvider.cs
│ ├── Activator.cs
│ └── AggregateException.cs
└── nanoFramework.DependencyInjection.nfproj
├── NuGet.Config
├── tests
├── packages.config
├── Fakes
│ ├── IService1.cs
│ ├── IService3.cs
│ ├── IFakeObject.cs
│ ├── IFakeService.cs
│ ├── IRootService.cs
│ ├── Service1.cs
│ ├── Service3.cs
│ ├── FakeObject.cs
│ ├── IFactoryService.cs
│ ├── IStructFakeService.cs
│ ├── IFakeMultipleService.cs
│ ├── INonexistentService.cs
│ ├── IService2.cs
│ ├── FakeOneMultipleService.cs
│ ├── FakeTwoMultipleService.cs
│ ├── PocoClass.cs
│ ├── AnotherClass.cs
│ ├── ClassWithThrowingCtor.cs
│ ├── ClassWithThrowingEmptyCtor.cs
│ ├── StructFakeService.cs
│ ├── Service2.cs
│ ├── CreationCountFakeService.cs
│ ├── AnotherClassAcceptingData.cs
│ ├── FakeService .cs
│ ├── InstanceCountServices
│ │ ├── TransientInstanceCountService.cs
│ │ └── SingletonInstanceCountService.cs
│ ├── ClassWithAmbiguousCtors.cs
│ ├── ClassWithNestedReferencesToProvider.cs
│ ├── RootService.cs
│ ├── ClassWithMultipleCtors.cs
│ └── ClassWithPrimitiveBinding.cs
├── nano.runsettings
├── packages.lock.json
├── Properties
│ └── AssemblyInfo.cs
├── ServiceProviderTests.cs
├── AggregateExceptionTests.cs
├── ActivatorTests.cs
├── ServiceProviderExtensionsTests.cs
├── nanoFramework.DependencyInjection.UnitTests.nfproj
├── ServiceCollectionDescriptorExtensionsTests.cs
├── ActivatorUtilitiesTests.cs
└── ServiceCollectionTests.cs
├── .github
├── workflows
│ ├── generate-changelog.yml
│ ├── pr-checks.yml
│ ├── keep-repo-active.yml
│ └── update-dependencies.yml
└── .changelog-config.json
├── version.json
├── LICENSE.md
├── nanoFramework.DependencyInjection.nuspec
├── nanoFramework.DependencyInjection.sln
├── .gitattributes
├── azure-pipelines.yml
├── CHANGELOG.md
├── .gitignore
└── README.md
/assets/nf-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nanoframework/nanoFramework.DependencyInjection/HEAD/assets/nf-logo.png
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 |
3 | # Default severity for all analyzer diagnostics
4 | dotnet_analyzer_diagnostic.severity = silent
5 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nanoframework/nanoFramework.DependencyInjection/HEAD/nanoFramework.DependencyInjection/key.snk
--------------------------------------------------------------------------------
/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/tests/Fakes/IService1.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | internal interface IService1
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/IService3.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | internal interface IService3
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/IFakeObject.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public interface IFakeObject
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/IFakeService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public interface IFakeService
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/IRootService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | internal interface IRootService
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/Service1.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | internal class Service1 : IService1
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/Service3.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | internal class Service3 : IService3
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/FakeObject.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public class FakeObject : IFakeObject
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/IFactoryService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public interface IFactoryService
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/IStructFakeService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public interface IStructFakeService
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/tests/Fakes/IFakeMultipleService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public interface IFakeMultipleService
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/INonexistentService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public interface INonexistentService
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/IService2.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | internal interface IService2
9 | {
10 | IService3 Service3 { get; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/Fakes/FakeOneMultipleService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public class FakeOneMultipleService : IFakeMultipleService
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/FakeTwoMultipleService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public class FakeTwoMultipleService : IFakeMultipleService
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/Fakes/PocoClass.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public class PocoClass
9 | {
10 | public PocoClass()
11 | {
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.github/workflows/generate-changelog.yml:
--------------------------------------------------------------------------------
1 | # Copyright (c) .NET Foundation and Contributors
2 | # See LICENSE file in the project root for full license information.
3 |
4 | name: Generate Changelog
5 | run-name: Generate changelog
6 |
7 | on:
8 | push:
9 | tags:
10 | - '*'
11 |
12 | jobs:
13 | compose_changelog:
14 | name: nanoFramework
15 | uses: nanoframework/nf-tools/.github/workflows/generate-changelog.yml@main
16 | secrets: inherit
17 |
--------------------------------------------------------------------------------
/tests/Fakes/AnotherClass.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public class AnotherClass
9 | {
10 | public AnotherClass(IFakeService fakeService)
11 | {
12 | FakeService = fakeService;
13 | }
14 |
15 | public IFakeService FakeService { get; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/Fakes/ClassWithThrowingCtor.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
9 | {
10 | public class ClassWithThrowingCtor
11 | {
12 | public ClassWithThrowingCtor(FakeService service)
13 | {
14 | throw new Exception(nameof(ClassWithThrowingCtor));
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/Fakes/ClassWithThrowingEmptyCtor.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
9 | {
10 | public class ClassWithThrowingEmptyCtor
11 | {
12 | public ClassWithThrowingEmptyCtor()
13 | {
14 | throw new Exception(nameof(ClassWithThrowingEmptyCtor));
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/Fakes/StructFakeService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public struct StructFakeService : IStructFakeService
9 | {
10 | private readonly IFakeObject _fakeObject;
11 |
12 | public StructFakeService(IFakeObject fakeobject)
13 | {
14 | _fakeObject = fakeobject;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.github/workflows/pr-checks.yml:
--------------------------------------------------------------------------------
1 | # Copyright (c) .NET Foundation and Contributors
2 | # See LICENSE file in the project root for full license information.
3 |
4 | name: PR Checks
5 |
6 | on:
7 | pull_request:
8 |
9 | jobs:
10 | check_package_lock:
11 | name: nanoFramework
12 | uses: nanoframework/nf-tools/.github/workflows/check-package-lock.yml@main
13 | check_nuget_latest:
14 | name: nanoFramework
15 | uses: nanoframework/nf-tools/.github/workflows/check-packages-updated.yml@main
16 | secrets: inherit
17 | with:
18 | solution: 'nanoFramework.DependencyInjection.sln'
19 |
--------------------------------------------------------------------------------
/tests/Fakes/Service2.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
9 | {
10 | internal class Service2 : IService2
11 | {
12 | public IService3 Service3 { get; private set; }
13 |
14 | public Service2(IService3 service3)
15 | {
16 | if (service3 == null)
17 | {
18 | throw new ArgumentNullException("service3");
19 | }
20 |
21 | Service3 = service3;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.github/workflows/keep-repo-active.yml:
--------------------------------------------------------------------------------
1 | # Copyright (c) .NET Foundation and Contributors
2 | # See LICENSE file in the project root for full license information.
3 |
4 | # This workflow will periodically make an empty commit to keep the repository active thus preventing the workflows from being disabled.
5 |
6 | name: Keep repository active
7 |
8 | on:
9 | schedule:
10 | # every 2 weeks at 00:00 UTC
11 | - cron: '0 0 */2 * *'
12 | repository_dispatch:
13 | types: keep-repo-active
14 |
15 | jobs:
16 | update-dependencies:
17 | name: nanoFramework
18 | uses: nanoframework/nf-tools/.github/workflows/keep-repo-active.yml@main
19 | secrets: inherit
20 |
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3 | "version": "1.1",
4 | "assemblyVersion": {
5 | "precision": "build"
6 | },
7 | "semVer1NumericIdentifierPadding": 3,
8 | "nuGetPackageVersion": {
9 | "semVer": 2.0
10 | },
11 | "publicReleaseRefSpec": [
12 | "^refs/heads/main$",
13 | "^refs/heads/v\\d+(?:\\.\\d+)?$"
14 | ],
15 | "cloudBuild": {
16 | "setAllVariables": true
17 | },
18 | "release": {
19 | "branchName": "release-v{version}",
20 | "versionIncrement": "build",
21 | "firstUnstableTag": "preview"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/tests/Fakes/CreationCountFakeService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public class CreationCountFakeService
9 | {
10 | public static readonly object InstanceLock = new object();
11 |
12 | public CreationCountFakeService(IFakeService dependency)
13 | {
14 | InstanceCount++;
15 | InstanceId = InstanceCount;
16 | }
17 |
18 | public static int InstanceCount { get; set; }
19 |
20 | public int InstanceId { get; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/nano.runsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 1
6 | .\TestResults
7 | 120000
8 | net48
9 | x64
10 |
11 |
12 | None
13 | False
14 |
15 |
--------------------------------------------------------------------------------
/tests/Fakes/AnotherClassAcceptingData.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public class AnotherClassAcceptingData
9 | {
10 | public AnotherClassAcceptingData(IFakeService fakeService, string one, string two)
11 | {
12 | FakeService = fakeService;
13 | One = one;
14 | Two = two;
15 | }
16 |
17 | public IFakeService FakeService { get; }
18 |
19 | public string One { get; }
20 |
21 | public string Two { get; }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/tests/packages.lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "dependencies": {
4 | ".NETnanoFramework,Version=v1.0": {
5 | "nanoFramework.CoreLibrary": {
6 | "type": "Direct",
7 | "requested": "[1.17.11, 1.17.11]",
8 | "resolved": "1.17.11",
9 | "contentHash": "HezzAc0o2XrSGf85xSeD/6xsO6ohF9hX6/iMQ1IZS6Zw6umr4WfAN2Jv0BrPxkaYwzEegJxxZujkHoUIAqtOMw=="
10 | },
11 | "nanoFramework.TestFramework": {
12 | "type": "Direct",
13 | "requested": "[3.0.77, 3.0.77]",
14 | "resolved": "3.0.77",
15 | "contentHash": "Py5W1oN84KMBmOOHCzdz6pyi3bZTnQu9BoqIx0KGqkhG3V8kGoem/t+BuCM0pMIWAyl2iMP1n2S9624YXmBJZw=="
16 | }
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/IServiceScope.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace Microsoft.Extensions.DependencyInjection
9 | {
10 | ///
11 | /// Defines scope for .
12 | ///
13 | public interface IServiceScope : IDisposable
14 | {
15 | ///
16 | /// The used to resolve dependencies from the scope.
17 | ///
18 | IServiceProvider ServiceProvider { get; }
19 | }
20 | }
--------------------------------------------------------------------------------
/tests/Fakes/FakeService .cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
9 | {
10 | public class FakeService : IFakeService, IDisposable
11 | {
12 | public PocoClass Value { get; set; }
13 |
14 | public bool Disposed { get; private set; }
15 |
16 | public void Dispose()
17 | {
18 | if (Disposed)
19 | {
20 | throw new ObjectDisposedException(nameof(FakeService));
21 | }
22 |
23 | Disposed = true;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/packages.lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "dependencies": {
4 | ".NETnanoFramework,Version=v1.0": {
5 | "nanoFramework.CoreLibrary": {
6 | "type": "Direct",
7 | "requested": "[1.17.11, 1.17.11]",
8 | "resolved": "1.17.11",
9 | "contentHash": "HezzAc0o2XrSGf85xSeD/6xsO6ohF9hX6/iMQ1IZS6Zw6umr4WfAN2Jv0BrPxkaYwzEegJxxZujkHoUIAqtOMw=="
10 | },
11 | "Nerdbank.GitVersioning": {
12 | "type": "Direct",
13 | "requested": "[3.9.50, 3.9.50]",
14 | "resolved": "3.9.50",
15 | "contentHash": "HtOgGF6jZ+WYbXnCUCYPT8Y2d6mIJo9ozjK/FINTRsXdm4Zgv9GehUMa7EFoGQkqrMcDJNOIDwCmENnvXg4UbA=="
16 | }
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/.github/workflows/update-dependencies.yml:
--------------------------------------------------------------------------------
1 | # Copyright (c) .NET Foundation and Contributors
2 | # See LICENSE file in the project root for full license information.
3 |
4 | # This workflow will periodically check .NET nanoFramework dependencies and updates them in the repository it's running.
5 |
6 | name: Daily update dependencies
7 |
8 | on:
9 | schedule:
10 | # At 00:00 UTC.
11 | - cron: '00 00 * * Tue,Thu'
12 | repository_dispatch:
13 | types: update-dependencies
14 |
15 | jobs:
16 | update-dependencies:
17 | name: nanoFramework
18 | uses: nanoframework/nf-tools/.github/workflows/update-dependencies.yml@main
19 | secrets: inherit
20 | with:
21 | solutionsToCheck: 'nanoFramework.DependencyInjection.sln'
22 |
--------------------------------------------------------------------------------
/tests/Fakes/InstanceCountServices/TransientInstanceCountService.cs:
--------------------------------------------------------------------------------
1 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes.InstanceCountServices
2 | {
3 | internal interface ITransientInstanceCountService
4 | {
5 | int Id { get; }
6 | }
7 |
8 | internal class TransientInstanceCountService : ITransientInstanceCountService
9 | {
10 | private readonly object _syncLock = new();
11 |
12 | public TransientInstanceCountService()
13 | {
14 | lock (_syncLock)
15 | {
16 | InstanceCount += 1;
17 | Id = InstanceCount;
18 | }
19 | }
20 |
21 | public int Id { get; }
22 | public static int InstanceCount { get; set; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/IServiceProviderIsService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Extensions.DependencyInjection
4 | {
5 | ///
6 | /// Optional service used to determine if the specified type is available from the .
7 | ///
8 | public interface IServiceProviderIsService
9 | {
10 | ///
11 | /// Determines if the specified service type is available from the .
12 | ///
13 | /// An object that specifies the type of service object to test.
14 | /// true if the specified service is a available, false if it is not.
15 | bool IsService(Type serviceType);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("nanoFramework.DependencyInjection")]
8 | [assembly: AssemblyCompany("nanoFramework Contributors")]
9 | [assembly: AssemblyProduct(".NET nanoframework nanoFramework.DependencyInjection")]
10 | [assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors")]
11 |
12 | // Setting ComVisible to false makes the types in this assembly not visible
13 | // to COM components. If you need to access a type in this assembly from
14 | // COM, set the ComVisible attribute to true on that type.
15 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/tests/Fakes/InstanceCountServices/SingletonInstanceCountService.cs:
--------------------------------------------------------------------------------
1 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes.InstanceCountServices
2 | {
3 | internal interface ISingletonInstanceCountService
4 | {
5 | int Id { get; }
6 | }
7 |
8 | internal class SingletonInstanceCountService : ISingletonInstanceCountService
9 | {
10 | private readonly ITransientInstanceCountService _transientInstanceCountService;
11 | private readonly object _syncLock = new();
12 |
13 | public SingletonInstanceCountService(ITransientInstanceCountService transientInstanceCountService)
14 | {
15 | _transientInstanceCountService = transientInstanceCountService;
16 |
17 | lock (_syncLock)
18 | {
19 | InstanceCount += 1;
20 | Id = InstanceCount;
21 | }
22 | }
23 |
24 | public int Id { get; }
25 | public static int InstanceCount { get; set; }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceLifetime.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace Microsoft.Extensions.DependencyInjection
7 | {
8 | ///
9 | /// Specifies the lifetime of a service in an .
10 | ///
11 | public enum ServiceLifetime
12 | {
13 | ///
14 | /// Specifies that a single instance of the service will be created.
15 | ///
16 | Singleton,
17 |
18 | ///
19 | /// Specifies that a new instance of the service will be created every time it is requested.
20 | ///
21 | Transient,
22 |
23 | ///
24 | /// Specifies that a single instance of the service will be created within a scope.
25 | ///
26 | Scoped
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/assets/readme.txt:
--------------------------------------------------------------------------------
1 | _____ _
2 | _ __ __ _ _ __ ___ | ___| __ __ _ _ __ ___ _____ _____ _ __| | __
3 | | '_ \ / _` | '_ \ / _ \| |_ | '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
4 | | | | | (_| | | | | (_) | _|| | | (_| | | | | | | __/\ V V / (_) | | | <
5 | |_| |_|\__,_|_| |_|\___/|_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_\
6 |
7 | ===================================================================================
8 |
9 | API docs: https://docs.nanoframework.net/api/nanoFramework.DependencyInjection.html
10 |
11 | Browse our samples repository: https://github.com/nanoframework/samples
12 |
13 | Check our documentation online: https://docs.nanoframework.net/
14 |
15 | Join our lively Discord community: https://discord.gg/gCyBu8T
16 |
17 | Report issues: https://github.com/nanoframework/Home/issues
18 |
19 | Follow us on Twitter: https://twitter.com/nanoframework
20 |
21 | Follow our YouTube channel: https://www.youtube.com/c/nanoFramework
22 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) .NET Foundation and Contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("nanoFramework.DependencyInjection.Tests")]
8 | [assembly: AssemblyCompany("nanoFramework Contributors")]
9 | [assembly: AssemblyProduct(".NET nanoframework nanoFramework.DependencyInjection Tests")]
10 | [assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors")]
11 |
12 | //////////////////////////////////////////////////////
13 | // this assembly does NOT have a native counterpart //
14 | //////////////////////////////////////////////////////
15 | ////////////////////////////////////////////////////////////////
16 | [assembly: AssemblyNativeVersion("0.0.0.0")]
17 | ////////////////////////////////////////////////////////////////
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/tests/Fakes/ClassWithAmbiguousCtors.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
7 | {
8 | public class ClassWithAmbiguousCtors
9 | {
10 | public ClassWithAmbiguousCtors(string data)
11 | {
12 | CtorUsed = "string";
13 | }
14 |
15 | public ClassWithAmbiguousCtors(IFakeService service, string data)
16 | {
17 | CtorUsed = "IFakeService, string";
18 | }
19 |
20 | public ClassWithAmbiguousCtors(IFakeService service, int data)
21 | {
22 | CtorUsed = "IFakeService, int";
23 | }
24 |
25 | public ClassWithAmbiguousCtors(IFakeService service, string data1, int data2)
26 | {
27 | FakeService = service;
28 | Data1 = data1;
29 | Data2 = data2;
30 |
31 | CtorUsed = "IFakeService, string, string";
32 | }
33 |
34 | public IFakeService FakeService { get; }
35 |
36 | public string Data1 { get; }
37 |
38 | public int Data2 { get; }
39 | public string CtorUsed { get; set; }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/Fakes/ClassWithNestedReferencesToProvider.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
9 | {
10 | public class ClassWithNestedReferencesToProvider : IDisposable
11 | {
12 | private IServiceProvider _serviceProvider;
13 | private ClassWithNestedReferencesToProvider _nested;
14 |
15 | public ClassWithNestedReferencesToProvider(IServiceProvider serviceProvider)
16 | {
17 | _serviceProvider = serviceProvider;
18 | _nested = new ClassWithNestedReferencesToProvider(_serviceProvider, 0);
19 | }
20 |
21 | private ClassWithNestedReferencesToProvider(IServiceProvider serviceProvider, int level)
22 | {
23 | _serviceProvider = serviceProvider;
24 | if (level > 1)
25 | {
26 | _nested = new ClassWithNestedReferencesToProvider(_serviceProvider, level + 1);
27 | }
28 | }
29 |
30 | public void Dispose()
31 | {
32 | _nested?.Dispose();
33 | (_serviceProvider as IDisposable)?.Dispose();
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceProviderOptions.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace Microsoft.Extensions.DependencyInjection
9 | {
10 | ///
11 | /// Options for configuring various behaviors of the default implementation.
12 | ///
13 | public class ServiceProviderOptions
14 | {
15 | // Avoid allocating objects in the default case
16 | internal static readonly ServiceProviderOptions Default = new ServiceProviderOptions();
17 |
18 | ///
19 | /// to perform check verifying that scoped services never gets resolved from root provider; otherwise . Defaults to .
20 | ///
21 | public bool ValidateScopes { get; set; }
22 |
23 | ///
24 | /// to perform check verifying that all services can be created during BuildServiceProvider call; otherwise . Defaults to .
25 | ///
26 | public bool ValidateOnBuild { get; set; }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tests/Fakes/RootService.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
9 | {
10 | internal class RootService : IRootService
11 | {
12 | private readonly IService1 _service1;
13 | private readonly IService2 _service2;
14 |
15 | public string StringProperty { get; set; }
16 |
17 | public int IntProperty { get; set; }
18 |
19 | internal IService1 Service1 => _service1;
20 |
21 | internal IService2 Service2 => _service2;
22 |
23 | public RootService(IService1 service1, IService2 service2)
24 | : this(service1, service2, "default", 2000)
25 | {
26 | }
27 |
28 | public RootService(IService1 service1, IService2 service2, string stringProperty, int intProperty)
29 | {
30 | if (service1 == null)
31 | {
32 | throw new ArgumentNullException(nameof(service1));
33 | }
34 |
35 | if (service2 == null)
36 | {
37 | throw new ArgumentNullException(nameof(service2));
38 | }
39 |
40 | _service1 = service1;
41 | _service2 = service2;
42 | StringProperty = stringProperty;
43 | IntProperty = intProperty;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/System/IServiceProvider.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace System
7 | {
8 | ///
9 | /// Defines a mechanism for retrieving a service object; that is, an object that provides custom support to other objects.
10 | ///
11 | public interface IServiceProvider
12 | {
13 | ///
14 | /// Gets the service object of the specified type.
15 | ///
16 | /// An object that specifies the type of service object to get.
17 | ///
18 | /// A service object of type . -or- null if there is no service object of type .
19 | ///
20 | object GetService(Type serviceType);
21 |
22 | ///
23 | /// Gets the service objects of the specified type.
24 | ///
25 | /// An array object that specifies the type of service object to get.
26 | ///
27 | /// A service object array of type . -or- array empty if there is no service object of type .
28 | ///
29 | object[] GetService(Type[] serviceType);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/Fakes/ClassWithMultipleCtors.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System.Collections;
7 |
8 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
9 | {
10 | public class ClassWithMultipleCtors
11 | {
12 | public ClassWithMultipleCtors(string data)
13 | {
14 | CtorUsed = 0;
15 | }
16 |
17 | public ClassWithMultipleCtors(IFakeService service, string data)
18 | {
19 | CtorUsed = 1;
20 | }
21 |
22 | public ClassWithMultipleCtors(IFakeService service, string data1, int data2)
23 | {
24 | FakeService = service;
25 | Data1 = data1;
26 | Data2 = data2;
27 |
28 | CtorUsed = 2;
29 | }
30 |
31 | public ClassWithMultipleCtors(IFakeService service, ICollection collection, string data1, int data2)
32 | {
33 | FakeService = service;
34 | Data1 = data1;
35 | Data2 = data2;
36 | Collection = collection;
37 | CtorUsed = 3;
38 | }
39 |
40 | public IFakeService FakeService { get; }
41 |
42 | public string Data1 { get; }
43 |
44 | public int Data2 { get; }
45 |
46 | public int CtorUsed { get; set; }
47 |
48 | public ICollection Collection { get; set; }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tests/ServiceProviderTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using nanoFramework.TestFramework;
3 | using nanoFramework.DependencyInjection.UnitTests.Fakes.InstanceCountServices;
4 |
5 | namespace nanoFramework.DependencyInjection.UnitTests
6 | {
7 | [TestClass]
8 | public class ServiceProviderTests
9 | {
10 | [Cleanup]
11 | public void Cleanup()
12 | {
13 | SingletonInstanceCountService.InstanceCount = 0;
14 | TransientInstanceCountService.InstanceCount = 0;
15 | }
16 |
17 | [TestMethod]
18 | public void GetService_should_only_create_a_single_instance_of_transient_dependencies()
19 | {
20 | // Arrange
21 | var serviceCollection = new ServiceCollection();
22 | serviceCollection.AddSingleton(typeof(ISingletonInstanceCountService), typeof(SingletonInstanceCountService));
23 | serviceCollection.AddTransient(typeof(ITransientInstanceCountService), typeof(TransientInstanceCountService));
24 |
25 | var sut = serviceCollection.BuildServiceProvider();
26 |
27 | // Act
28 | var service = (ISingletonInstanceCountService) sut.GetRequiredService(typeof(ISingletonInstanceCountService));
29 |
30 | // Assert
31 | Assert.AreEqual(1, SingletonInstanceCountService.InstanceCount);
32 | Assert.AreEqual(1, TransientInstanceCountService.InstanceCount);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/TypeExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 |
4 | namespace Microsoft.Extensions.DependencyInjection
5 | {
6 | ///
7 | /// Contains extension methods for .
8 | ///
9 | internal static class TypeExtensions
10 | {
11 | ///
12 | /// Compares this instance to a specified type and returns an indication if resolvable value.
13 | ///
14 | /// The current
15 | public static bool IsResolvable(this Type type)
16 | {
17 | return type == typeof(string)
18 | || type == typeof(bool)
19 | || type == typeof(byte)
20 | || type == typeof(sbyte)
21 | || type == typeof(short)
22 | || type == typeof(ushort)
23 | || type == typeof(int)
24 | || type == typeof(uint)
25 | || type == typeof(long)
26 | || type == typeof(ulong)
27 | || type == typeof(double)
28 | || type == typeof(float)
29 | || type == typeof(object)
30 | || type == typeof(DateTime)
31 | || type == typeof(TimeSpan)
32 | || type == typeof(Guid)
33 | || type == typeof(Array)
34 | || type == typeof(ArrayList);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceScope.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 | using System.Diagnostics;
8 |
9 | namespace Microsoft.Extensions.DependencyInjection
10 | {
11 | ///
12 | /// An implementation that implements .
13 | ///
14 | [DebuggerDisplay("{ServiceProvider,nq}")]
15 | public readonly struct ServiceScope : IServiceScope
16 | {
17 | private readonly IServiceScope _serviceScope;
18 |
19 | ///
20 | /// Initializes a new instance of the struct.
21 | /// Wraps an instance of .
22 | ///
23 | /// The instance to wrap.
24 | public ServiceScope(IServiceScope serviceScope)
25 | {
26 | if (serviceScope == null)
27 | {
28 | throw new ArgumentNullException();
29 | }
30 |
31 | _serviceScope = serviceScope;
32 | }
33 |
34 | ///
35 | public IServiceProvider ServiceProvider => _serviceScope.ServiceProvider;
36 |
37 | ///
38 | public void Dispose()
39 | {
40 | _serviceScope.Dispose();
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/.github/.changelog-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "categories": [
3 | {
4 | "title": "## New Features and enhancements",
5 | "labels": [
6 | "Type: enhancement"
7 | ],
8 | "exhaustive": true
9 | },
10 | {
11 | "title": "## Bug Fixes",
12 | "labels": [
13 | "Type: bug"
14 | ],
15 | "exhaustive": true
16 | },
17 | {
18 | "title": "## Documentation",
19 | "labels": [
20 | "Type: documentation"
21 | ],
22 | "exhaustive": true
23 | },
24 | {
25 | "title": "## ⚠️ Breaking Changes",
26 | "labels": [
27 | "Breaking-Change"
28 | ],
29 | "exhaustive": true
30 | },
31 | {
32 | "title": "## Updated dependencies",
33 | "labels": [
34 | "Type: dependencies"
35 | ],
36 | "exhaustive": true
37 | }
38 | ],
39 | "sort": "ASC",
40 | "template": "${{CHANGELOG}}\n\n**Full Changelog:** ${{RELEASE_DIFF}}\n\nThe following NuGet package is available from this release:\n\n:package: [nanoFramework.DependencyInjection](https://www.nuget.org/packages/nanoFramework.DependencyInjection/)",
41 | "pr_template": "* ${{TITLE}} by @${{AUTHOR}} in #${{NUMBER}}",
42 | "empty_template": "- no changes",
43 | "max_tags_to_fetch": 200,
44 | "max_pull_requests": 200
45 | }
46 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceCollectionContainerBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace Microsoft.Extensions.DependencyInjection
7 | {
8 | ///
9 | /// Extension methods for building a from an .
10 | ///
11 | public static class ServiceCollectionContainerBuilderExtensions
12 | {
13 | ///
14 | /// Creates a containing services from the provided .
15 | ///
16 | /// The containing service descriptors.
17 | /// The .
18 | public static ServiceProvider BuildServiceProvider(this IServiceCollection services)
19 | {
20 | return services.BuildServiceProvider(ServiceProviderOptions.Default);
21 | }
22 |
23 | ///
24 | /// Creates a containing services from the provided
25 | /// optionally enabling scope validation.
26 | ///
27 | /// The containing service descriptors.
28 | /// Configures various service provider behaviors.
29 | /// The .
30 | public static ServiceProvider BuildServiceProvider(this IServiceCollection services, ServiceProviderOptions options)
31 | {
32 | return new ServiceProvider(services, options);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | nanoFramework.DependencyInjection
5 | $version$
6 | nanoFramework.DependencyInjection
7 | nanoframework
8 | false
9 | LICENSE.md
10 |
11 |
12 | docs\README.md
13 | false
14 | https://github.com/nanoframework/nanoFramework.DependencyInjection
15 | images\nf-logo.png
16 |
17 | Copyright (c) .NET Foundation and Contributors
18 | This package includes the nanoFramework.DependencyInjection assembly for .NET nanoFramework C# projects.
19 | nanoFramework C# csharp netmf netnf dependencyinjection
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/tests/Fakes/ClassWithPrimitiveBinding.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 |
4 | using System;
5 | using System.Collections;
6 |
7 | namespace nanoFramework.DependencyInjection.UnitTests.Fakes
8 | {
9 | public class ClassWithPrimitiveBinding
10 | {
11 | public string Str { get; set; }
12 |
13 | public bool Boolean { get; set; }
14 |
15 | public byte Byte { get; set; }
16 |
17 | public sbyte SByte { get; set; }
18 |
19 | public short Short { get; set; }
20 |
21 | public ushort Ushort { get; set; }
22 |
23 | public int Int { get; set; }
24 |
25 | public uint UInt { get; set; }
26 |
27 | public long Long { get; set; }
28 |
29 | public ulong Ulong { get; set; }
30 |
31 | public double Double { get; set; }
32 |
33 | public float Float { get; set; }
34 |
35 | public object Obj { get; set; }
36 |
37 | public DateTime DateTime { get; set; }
38 |
39 | public TimeSpan TimeSpan { get; set; }
40 |
41 | public Guid Guid { get; set; }
42 |
43 | public Array Array { get; set; }
44 |
45 | public ArrayList ArrayList { get; set; }
46 |
47 | public ClassWithPrimitiveBinding(
48 | string str,
49 | bool boolean,
50 | byte @byte,
51 | sbyte sByte,
52 | short @short,
53 | ushort @ushort,
54 | int @int,
55 | uint uInt,
56 | long @long,
57 | ulong @ulong,
58 | double @double,
59 | float @float,
60 | object obj,
61 | DateTime dateTime,
62 | TimeSpan timeSpan,
63 | Guid guid,
64 | Array array,
65 | ArrayList arrayList)
66 | {
67 | Str = str;
68 | Boolean = boolean;
69 | Byte = @byte;
70 | SByte = sByte;
71 | Short = @short;
72 | Ushort = @ushort;
73 | Int = @int;
74 | UInt = uInt;
75 | Long = @long;
76 | Ulong = @ulong;
77 | Double = @double;
78 | Float = @float;
79 | Obj = obj;
80 | DateTime = dateTime;
81 | TimeSpan = timeSpan;
82 | Guid = guid;
83 | Array = array;
84 | ArrayList = arrayList;
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/tests/AggregateExceptionTests.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 | using System.Collections;
8 | using nanoFramework.TestFramework;
9 |
10 | namespace nanoFramework.DependencyInjection.UnitTests
11 | {
12 | [TestClass]
13 | public class AggregateExceptionTests
14 | {
15 | [TestMethod]
16 | public static void ConstructorBasic()
17 | {
18 | AggregateException ex = new AggregateException();
19 | Assert.AreEqual(0, ex.InnerExceptions.Count);
20 | Assert.IsTrue(ex.Message != null, "RunAggregateException_Constructor: FAILED. Message property is null when the default constructor is used, expected a default message");
21 |
22 | ex = new AggregateException("message");
23 | Assert.AreEqual(0, ex.InnerExceptions.Count);
24 | Assert.IsTrue(ex.Message != null, "RunAggregateException_Constructor: FAILED. Message property is null when the default constructor(string) is used");
25 |
26 | ex = new AggregateException("message", new Exception());
27 | Assert.AreEqual(1, ex.InnerExceptions.Count);
28 | Assert.IsTrue(ex.Message != null, "RunAggregateException_Constructor: FAILED. Message property is null when the default constructor(string, Exception) is used");
29 | }
30 |
31 | [TestMethod]
32 | public static void ConstructorInvalidArguments()
33 | {
34 | Assert.ThrowsException(typeof(ArgumentNullException), () => new AggregateException("message", (Exception)null));
35 | Assert.ThrowsException(typeof(ArgumentNullException), () => new AggregateException("message", new ArrayList() { null }));
36 | }
37 |
38 | [TestMethod]
39 | public static void Message()
40 | {
41 | Exception exceptionA = new Exception("A");
42 | Exception exceptionB = new Exception("B");
43 | Exception exceptionC = new Exception("C");
44 |
45 | AggregateException aggExceptionBase = new AggregateException("message", exceptionA, exceptionB, exceptionC);
46 | Assert.AreEqual("message (A) (B) (C)", aggExceptionBase.Message);
47 | //Assert.Equal("message (A) (B) (C)\n---> (Inner Exception #0) System.Exception: A <---\n---> (Inner Exception #1) System.Exception: B <---\n---> (Inner Exception #2) System.Exception: C <---\n", aggExceptionBase.ToString());
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.2.32519.379
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.DependencyInjection", "nanoFramework.DependencyInjection\nanoFramework.DependencyInjection.nfproj", "{A2B2222C-0553-4877-8CF1-4458B30C0081}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5CA8DDDF-50C5-4044-A78C-170228780423}"
9 | ProjectSection(SolutionItems) = preProject
10 | .runsettings = .runsettings
11 | nanoframework.DependencyInjection.nuspec = nanoframework.DependencyInjection.nuspec
12 | README.md = README.md
13 | version.json = version.json
14 | EndProjectSection
15 | EndProject
16 | Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.DependencyInjection.UnitTests", "tests\nanoFramework.DependencyInjection.UnitTests.nfproj", "{547A718F-591B-4D7F-A144-8D57C0F98276}"
17 | EndProject
18 | Global
19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 | Debug|Any CPU = Debug|Any CPU
21 | Release|Any CPU = Release|Any CPU
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
27 | {A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.Build.0 = Release|Any CPU
29 | {A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.Deploy.0 = Release|Any CPU
30 | {547A718F-591B-4D7F-A144-8D57C0F98276}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {547A718F-591B-4D7F-A144-8D57C0F98276}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {547A718F-591B-4D7F-A144-8D57C0F98276}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
33 | {547A718F-591B-4D7F-A144-8D57C0F98276}.Release|Any CPU.ActiveCfg = Release|Any CPU
34 | {547A718F-591B-4D7F-A144-8D57C0F98276}.Release|Any CPU.Build.0 = Release|Any CPU
35 | {547A718F-591B-4D7F-A144-8D57C0F98276}.Release|Any CPU.Deploy.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | GlobalSection(ExtensibilityGlobals) = postSolution
41 | SolutionGuid = {F36078E1-F784-459A-B4A7-330B3F2BBEA0}
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceProvider.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 | using System.Collections;
8 |
9 | namespace Microsoft.Extensions.DependencyInjection
10 | {
11 | ///
12 | /// The default .
13 | ///
14 | /// Some services are not able to be constructed.
15 | public sealed class ServiceProvider : IServiceProvider, IServiceProviderIsService, IDisposable
16 | {
17 | private bool _disposed;
18 |
19 | internal ServiceProviderEngine Engine { get; }
20 |
21 | internal ServiceProvider(IServiceCollection services, ServiceProviderOptions options)
22 | {
23 | if (services == null)
24 | {
25 | throw new ArgumentNullException();
26 | }
27 |
28 | if (options == null)
29 | {
30 | throw new ArgumentNullException();
31 | }
32 |
33 | Engine = GetEngine();
34 | Engine.Services = services;
35 | Engine.Services.Add(new ServiceDescriptor(typeof(IServiceProvider), this));
36 | Engine.Options = options;
37 |
38 | if (options.ValidateOnBuild)
39 | {
40 | ArrayList exceptions = null;
41 |
42 | foreach (ServiceDescriptor descriptor in services)
43 | {
44 | try
45 | {
46 | Engine.ValidateService(descriptor);
47 | }
48 | catch (Exception ex)
49 | {
50 | exceptions ??= new ArrayList();
51 | exceptions.Add(ex);
52 | }
53 | }
54 |
55 | if (exceptions != null)
56 | {
57 | throw new AggregateException(string.Empty, exceptions);
58 | }
59 | }
60 | }
61 |
62 | ///
63 | public object GetService(Type serviceType)
64 | {
65 | if (_disposed)
66 | {
67 | throw new ObjectDisposedException();
68 | }
69 |
70 | return Engine.GetService(serviceType);
71 | }
72 |
73 | ///
74 | public object[] GetService(Type[] serviceType)
75 | {
76 | if (_disposed)
77 | {
78 | throw new ObjectDisposedException();
79 | }
80 |
81 | return Engine.GetService(serviceType);
82 | }
83 |
84 | ///
85 | public IServiceScope CreateScope()
86 | {
87 | return new ServiceProviderEngineScope(this);
88 | }
89 |
90 | ///
91 | public void Dispose()
92 | {
93 | if (_disposed)
94 | {
95 | return;
96 | }
97 |
98 | _disposed = true;
99 | Engine.DisposeServices();
100 | }
101 |
102 | private ServiceProviderEngine GetEngine()
103 | {
104 | return ServiceProviderEngine.Instance;
105 | }
106 |
107 | ///
108 | public bool IsService(Type serviceType)
109 | {
110 | return Engine.IsService(serviceType);
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/IServiceCollection.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System.Collections;
7 |
8 | namespace Microsoft.Extensions.DependencyInjection
9 | {
10 | ///
11 | /// Default implementation of IServiceCollection.
12 | ///
13 | public interface IServiceCollection
14 | {
15 | ///
16 | /// Gets or sets the at the specified index.
17 | ///
18 | /// The zero-based index of the item to add.
19 | ServiceDescriptor this[int index] { get; set; }
20 |
21 | ///
22 | /// Gets a value indicating whether the collection is read-only.
23 | ///
24 | bool IsReadOnly { get; }
25 |
26 | ///
27 | /// Gets the number of elements contained in the collection.
28 | ///
29 | int Count { get; }
30 |
31 | ///
32 | /// Adds an item to the collection.
33 | ///
34 | /// The to add.
35 | int Add(ServiceDescriptor item);
36 |
37 | ///
38 | /// Removes all from the collection.
39 | ///
40 | void Clear();
41 |
42 | ///
43 | /// Determines whether the collection contains a specific value.
44 | ///
45 | /// The to locate in the collection.
46 | bool Contains(ServiceDescriptor item);
47 |
48 | ///
49 | /// Copies the elements of the collection to an Array starting at a particular Array index.
50 | ///
51 | /// The one-dimensional Array that is the destination of the elements copied from. The Array must have zero-based indexing.
52 | /// The zero-based index in array at which copying begins.
53 | void CopyTo(ServiceDescriptor[] array, int arrayIndex);
54 |
55 | ///
56 | /// Returns an enumerator that iterates through a collection.
57 | ///
58 | IEnumerator GetEnumerator();
59 |
60 | ///
61 | /// Determines the index of a specific item in the collection.
62 | ///
63 | /// The to get the index of.
64 | int IndexOf(ServiceDescriptor item);
65 |
66 | ///
67 | /// Inserts an item to the collection at the specified index.
68 | ///
69 | /// The zero-based index at which should be inserted.
70 | /// The to insert.
71 | void Insert(int index, ServiceDescriptor item);
72 |
73 | ///
74 | /// Removes the first occurrence of a specific object from the collection.
75 | ///
76 | /// The to remove.
77 | void Remove(ServiceDescriptor item);
78 |
79 | ///
80 | /// Removes the item at the specified index.
81 | ///
82 | /// The zero-based index of the item to remove.
83 | void RemoveAt(int index);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # Copyright (c) .NET Foundation and Contributors
2 | # See LICENSE file in the project root for full license information.
3 |
4 | trigger:
5 | branches:
6 | include:
7 | - main
8 | - develop
9 | - release-*
10 | paths:
11 | exclude:
12 | - .gitignore
13 | - CHANGELOG.md
14 | - LICENSE.md
15 | - README.md
16 | - NuGet.Config
17 | - assets/*
18 | - .github/*
19 |
20 | tags:
21 | include:
22 | - v*
23 |
24 | # PR always trigger build
25 | pr:
26 | autoCancel: true
27 |
28 | # add nf-tools repo to resources (for Azure Pipelines templates)
29 | resources:
30 | repositories:
31 | - repository: templates
32 | type: github
33 | name: nanoframework/nf-tools
34 | endpoint: nanoframework
35 |
36 | variables:
37 | - name: nugetPackageName
38 | value: 'nanoFramework.DependencyInjection'
39 | - name: DOTNET_NOLOGO
40 | value: true
41 |
42 | jobs:
43 |
44 | ##############################
45 | - job: Build_Library
46 | condition: >-
47 | and(
48 | not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')),
49 | or(
50 | eq(variables['UPDATE_DEPENDENTS'], 'false'),
51 | eq(variables['StartReleaseCandidate'], 'true')
52 | )
53 | )
54 | pool:
55 | vmImage: 'windows-latest'
56 |
57 | variables:
58 | - group: sign-client-credentials
59 | - name: buildPlatform
60 | value: 'Any CPU'
61 | - name: buildConfiguration
62 | value: 'Release'
63 | - name: solution
64 | value: 'nanoFramework.DependencyInjection.sln'
65 |
66 | steps:
67 |
68 | # step from template @ nf-tools repo
69 | # all build, update and publish steps
70 | - template: azure-pipelines-templates/class-lib-build.yml@templates
71 | parameters:
72 | sonarCloudProject: 'nanoframework_nanoFramework.DependencyInjection'
73 | runUnitTests: true
74 | unitTestRunsettings: '$(System.DefaultWorkingDirectory)\tests\nano.runsettings'
75 |
76 | ##############################
77 | - job: Update_Dependents
78 | condition: >-
79 | or(
80 | and(
81 | startsWith(variables['Build.SourceBranch'], 'refs/tags/v'),
82 | eq(variables['StartReleaseCandidate'], 'false')
83 | ),
84 | and(
85 | contains(variables['getCommitMessage.COMMIT_MESSAGE'], '***UPDATE_DEPENDENTS***'),
86 | eq(variables['StartReleaseCandidate'], 'false')
87 | ),
88 | eq(variables['UPDATE_DEPENDENTS'], 'true')
89 | )
90 |
91 | pool:
92 | vmImage: 'windows-latest'
93 |
94 | steps:
95 | # need this here in order to persist GitHub credentials
96 | - checkout: self
97 | fetchDepth: 1
98 |
99 | # update dependents
100 | - template: azure-pipelines-templates/update-dependents.yml@templates
101 | parameters:
102 | packageName: '$(nugetPackageName)'
103 | repositoriesToUpdate: |
104 | nanoFramework.Hosting
105 |
106 | ##################################
107 | # report build failure to Discord
108 | - job: Report_Build_Failure
109 |
110 | dependsOn:
111 | - Build_Library
112 | - Update_Dependents
113 | condition: >-
114 | or(
115 | failed('Build_Library'),
116 | failed('Update_Dependents')
117 | )
118 |
119 | pool:
120 | vmImage: 'windows-latest'
121 |
122 | steps:
123 |
124 | - checkout: self
125 |
126 | # step from template @ nf-tools repo
127 | # report error
128 | - template: azure-pipelines-templates/discord-webhook-task.yml@templates
129 | parameters:
130 | status: 'failure'
131 | webhookUrl: '$(DiscordWebhook)'
132 | message: ''
133 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceCollection.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System.Collections;
7 |
8 | namespace Microsoft.Extensions.DependencyInjection
9 | {
10 | ///
11 | /// Default implementation of .
12 | ///
13 | public class ServiceCollection : IServiceCollection
14 | {
15 | private readonly object _syncLock = new();
16 | private readonly ArrayList _descriptors = [];
17 |
18 | ///
19 | public bool IsReadOnly => false;
20 |
21 | ///
22 | public int Count
23 | {
24 | get
25 | {
26 | lock (_syncLock)
27 | {
28 | return _descriptors.Count;
29 | }
30 | }
31 | }
32 |
33 | ///
34 | public ServiceDescriptor this[int index]
35 | {
36 | get
37 | {
38 | lock (_syncLock)
39 | {
40 | return (ServiceDescriptor)_descriptors[index];
41 | }
42 | }
43 |
44 | set
45 | {
46 | lock (_syncLock)
47 | {
48 | _descriptors[index] = value;
49 | }
50 | }
51 | }
52 |
53 | ///
54 | public int Add(ServiceDescriptor item)
55 | {
56 | lock (_syncLock)
57 | {
58 | return _descriptors.Add(item);
59 | }
60 | }
61 |
62 | ///
63 | public void Clear()
64 | {
65 | lock (_syncLock)
66 | {
67 | _descriptors.Clear();
68 | }
69 | }
70 |
71 | ///
72 | public bool Contains(ServiceDescriptor item)
73 | {
74 | lock (_syncLock)
75 | {
76 | return _descriptors.Contains(item);
77 | }
78 | }
79 |
80 | ///
81 | public void CopyTo(ServiceDescriptor[] array, int arrayIndex)
82 | {
83 | lock (_syncLock)
84 | {
85 | _descriptors.CopyTo(array, arrayIndex);
86 | }
87 | }
88 |
89 | ///
90 | public void Remove(ServiceDescriptor item)
91 | {
92 | lock (_syncLock)
93 | {
94 | _descriptors.Remove(item);
95 | }
96 | }
97 |
98 | ///
99 | public IEnumerator GetEnumerator()
100 | {
101 | lock (_syncLock)
102 | {
103 | return _descriptors.GetEnumerator();
104 | }
105 | }
106 |
107 | ///
108 | public int IndexOf(ServiceDescriptor item)
109 | {
110 | lock (_syncLock)
111 | {
112 | return _descriptors.IndexOf(item);
113 | }
114 | }
115 |
116 | ///
117 | public void Insert(int index, ServiceDescriptor item)
118 | {
119 | lock (_syncLock)
120 | {
121 | _descriptors.Insert(index, item);
122 | }
123 | }
124 |
125 | ///
126 | public void RemoveAt(int index)
127 | {
128 | lock (_syncLock)
129 | {
130 | _descriptors.RemoveAt(index);
131 | }
132 | }
133 | }
134 | }
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/System/Activator.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace System
7 | {
8 | ///
9 | /// Contains methods to create types of objects locally. This class cannot be inherited.
10 | ///
11 | public static class Activator
12 | {
13 | ///
14 | /// Creates an instance of the type whose name is specified, using the named assembly.
15 | ///
16 | /// The fully qualified name of the type to create an instance of.
17 | public static object CreateInstance(string typename)
18 | {
19 | Type type = Type.GetType(typename);
20 |
21 | if (type != null)
22 | {
23 | return CreateInstance(type);
24 | }
25 |
26 | return null;
27 | }
28 |
29 | ///
30 | /// Creates an instance of the specified type using that type's parameterless constructor.
31 | ///
32 | /// The type of object to create.
33 | public static object CreateInstance(Type type)
34 | {
35 | return CreateInstance(type, new Type[] { }, new object[] { });
36 | }
37 |
38 | ///
39 | /// Creates an instance of the specified type using the constructor that best matches the specified parameters.
40 | ///
41 | /// The type of object to create.
42 | /// An array of arguments that match in number, order, and type the parameters of the constructor to invoke.
43 | /// If is an empty array or null, the constructor that takes no parameters (the parameterless constructor) is invoked.
44 | public static object CreateInstance(Type type, params object[] args)
45 | {
46 | Type[] types = args != null ? new Type[args.Length] : new Type[] { };
47 |
48 | for (int index = types.Length - 1; index >= 0; index--)
49 | {
50 | types[index] = args?[index]?.GetType();
51 | }
52 |
53 | return CreateInstance(type, types, args);
54 | }
55 |
56 | ///
57 | /// Creates an instance of the specified type using the constructor that best matches the specified parameters.
58 | ///
59 | /// The type of object to create.
60 | /// An array of Type objects representing the number, order, and type of the parameters for the desired constructor.
61 | /// If types is an empty array or null, to get constructor that takes no parameters.
62 | /// An array of arguments that match in number, order, and type the parameters of the constructor to invoke.
63 | /// If is an empty array or null, the constructor that takes no parameters (the parameterless constructor) is invoked.
64 | /// can't be null.
65 | public static object CreateInstance(Type type, Type[] types, params object[] args)
66 | {
67 | if (type == null)
68 | {
69 | throw new ArgumentNullException();
70 | }
71 |
72 | if (types == null)
73 | {
74 | types = new Type[] { };
75 | }
76 |
77 | if (args == null)
78 | {
79 | args = new object[] { };
80 | }
81 |
82 | return type.GetConstructor(types).Invoke(args);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceProviderEngineScope.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace Microsoft.Extensions.DependencyInjection
9 | {
10 | ///
11 | /// The method ends the scope lifetime. Once Dispose
12 | /// is called, any scoped services that have been resolved from
13 | /// will be disposed.
14 | ///
15 | internal sealed class ServiceProviderEngineScope : IServiceScope, IServiceProvider
16 | {
17 | private bool _disposed;
18 |
19 | private readonly IServiceCollection _scopeServices = new ServiceCollection();
20 |
21 | ///
22 | /// The root service provider used to resolve dependencies from the scope.
23 | ///
24 | internal ServiceProvider RootProvider { get; }
25 |
26 | ///
27 | /// Creates instance of .
28 | ///
29 | /// The root service provider used to resolve dependencies from the scope.
30 | internal ServiceProviderEngineScope(ServiceProvider provider)
31 | {
32 | RootProvider = provider;
33 |
34 | CloneScopeServices();
35 | }
36 |
37 | ///
38 | /// The resolved from the scope.
39 | ///
40 | public IServiceProvider ServiceProvider => this;
41 |
42 | ///
43 | public object GetService(Type serviceType)
44 | {
45 | if (_disposed)
46 | {
47 | throw new ObjectDisposedException();
48 | }
49 |
50 | return RootProvider.Engine.GetService(serviceType, _scopeServices);
51 | }
52 |
53 | ///
54 | public object[] GetService(Type[] serviceType)
55 | {
56 | if (_disposed)
57 | {
58 | throw new ObjectDisposedException();
59 | }
60 |
61 | return RootProvider.Engine.GetService(serviceType, _scopeServices);
62 | }
63 |
64 | ///
65 | public IServiceScope CreateScope()
66 | {
67 | return new ServiceProviderEngineScope(RootProvider);
68 | }
69 |
70 | ///
71 | public void Dispose()
72 | {
73 | if (_disposed)
74 | {
75 | return;
76 | }
77 |
78 | _disposed = true;
79 | DisposeServices();
80 | }
81 |
82 | private void CloneScopeServices()
83 | {
84 | foreach (ServiceDescriptor descriptor in RootProvider.Engine.Services)
85 | {
86 | if (descriptor.Lifetime == ServiceLifetime.Scoped)
87 | {
88 | _scopeServices.Add(new ServiceDescriptor(
89 | descriptor.ServiceType, descriptor.ImplementationType, ServiceLifetime.Scoped));
90 | }
91 | }
92 | }
93 |
94 | private void DisposeServices()
95 | {
96 | for (int index = _scopeServices.Count - 1; index >= 0; index--)
97 | {
98 | if (_scopeServices[index].ImplementationInstance is IDisposable disposable)
99 | {
100 | #pragma warning disable S3966 //services must be disposed explicitly, otherwise ServiceRegisteredWithScopeIsDisposedWhenScopeIsDisposed test fails
101 | disposable.Dispose();
102 | #pragma warning restore S3966
103 | }
104 | }
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/tests/ActivatorTests.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | using nanoFramework.TestFramework;
9 |
10 | namespace nanoFramework.DependencyInjection.UnitTests
11 | {
12 | [TestClass]
13 | public class ActivatorTests
14 | {
15 | [TestMethod]
16 | public static void CreateInstance()
17 | {
18 | Choice c = (Choice)(Activator.CreateInstance(typeof(Choice)));
19 | Assert.AreEqual(1, c.I);
20 |
21 | c = (Choice)(Activator.CreateInstance(typeof(Choice).FullName));
22 | Assert.AreEqual(1, c.I);
23 |
24 | c = (Choice)(Activator.CreateInstance(typeof(Choice), null));
25 | Assert.AreEqual(1, c.I);
26 |
27 | c = (Choice)(Activator.CreateInstance(typeof(Choice), null, null));
28 | Assert.AreEqual(1, c.I);
29 |
30 | c = (Choice)(Activator.CreateInstance(typeof(Choice), new object[] { }));
31 | Assert.AreEqual(1, c.I);
32 |
33 | c = (Choice)(Activator.CreateInstance(typeof(Choice), new object[] { 42 }));
34 | Assert.AreEqual(2, c.I);
35 |
36 | c = (Choice)(Activator.CreateInstance(typeof(Choice), new object[] { "Hello" }));
37 | Assert.AreEqual(3, c.I);
38 |
39 | c = (Choice)(Activator.CreateInstance(typeof(Choice), new object[] { 5.1, "Hello" }));
40 | Assert.AreEqual(4, c.I);
41 | }
42 |
43 | [TestMethod]
44 | public static void CreateInstanceConstructorWithParamsParameter()
45 | {
46 | Choice c = (Choice)(Activator.CreateInstance(typeof(Choice), new object[] { new VarArgs(), new object[] { } }));
47 | Assert.AreEqual(5, c.I);
48 |
49 | c = (Choice)(Activator.CreateInstance(typeof(Choice), new object[] { new VarArgs(), new object[] { "P1" } }));
50 | Assert.AreEqual(5, c.I);
51 |
52 | c = (Choice)(Activator.CreateInstance(typeof(Choice), new object[] { new VarArgs(), new object[] { "P1", "P2" } }));
53 | Assert.AreEqual(5, c.I);
54 |
55 | c = (Choice)(Activator.CreateInstance(typeof(Choice), new object[] { new VarStringArgs(), new string[] { } }));
56 | Assert.AreEqual(6, c.I);
57 |
58 | c = (Choice)(Activator.CreateInstance(typeof(Choice), new object[] { new VarStringArgs(), new string[] { "P1" } }));
59 | Assert.AreEqual(6, c.I);
60 |
61 | // TODO:? c = (Choice1)(Activator.CreateInstance(typeof(Choice1), new object[] { new VarStringArgs(), "P1", "P2" }));
62 | c = (Choice)(Activator.CreateInstance(typeof(Choice), new object[] { new VarStringArgs(), new string[] { "P1", "P2" } }));
63 | Assert.AreEqual(6, c.I);
64 | }
65 |
66 | [TestMethod]
67 | public void CreateInstanceNullTypeThrowsArgumentNullException()
68 | {
69 | Assert.ThrowsException(typeof(ArgumentNullException), () => Activator.CreateInstance(null, new object[0]));
70 | }
71 |
72 | public class Choice
73 | {
74 | public Choice()
75 | {
76 | I = 1;
77 | }
78 |
79 | public Choice(int i)
80 | {
81 | I = 2;
82 | }
83 |
84 | public Choice(string s)
85 | {
86 | I = 3;
87 | }
88 |
89 | public Choice(double d, string optionalS = "Hey")
90 | {
91 | I = 4;
92 | }
93 |
94 | public Choice(VarArgs varArgs, params object[] parameters)
95 | {
96 | I = 5;
97 | }
98 |
99 | public Choice(VarStringArgs varArgs, params string[] parameters)
100 | {
101 | I = 6;
102 | }
103 |
104 | public Choice(VarIntArgs varArgs, params int[] parameters)
105 | {
106 | I = 7;
107 | }
108 |
109 | public int I;
110 | }
111 |
112 | public class VarArgs { }
113 |
114 | public class VarStringArgs { }
115 |
116 | public class VarIntArgs { }
117 | }
118 | }
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceProviderServiceExtensions.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace Microsoft.Extensions.DependencyInjection
9 | {
10 | ///
11 | /// Extension methods for getting services from an .
12 | ///
13 | public static class ServiceProviderServiceExtensions
14 | {
15 | ///
16 | /// Get an enumeration of services of type from the .
17 | ///
18 | /// The to retrieve the services from.
19 | /// An object that specifies the type of service object to get.
20 | /// An array of services of type .
21 | public static object[] GetServices(this IServiceProvider provider, Type serviceType)
22 | {
23 | if (provider == null)
24 | {
25 | throw new ArgumentNullException();
26 | }
27 |
28 | return provider.GetService(new Type[] { serviceType });
29 | }
30 |
31 | ///
32 | /// Get an enumeration of services of type from the .
33 | ///
34 | /// The to retrieve the services from.
35 | /// An array of object that specifies the type of service object to get.
36 | /// An array of services of type .
37 | /// 'provider' or 'serviceType' can't be .
38 | public static object[] GetServices(this IServiceProvider provider, Type[] serviceType)
39 | {
40 | if (provider == null)
41 | {
42 | throw new ArgumentNullException();
43 | }
44 |
45 | if (serviceType == null)
46 | {
47 | throw new ArgumentNullException();
48 | }
49 |
50 | return provider.GetService(serviceType);
51 | }
52 |
53 | ///
54 | /// Get service of type from the .
55 | ///
56 | /// The to retrieve the service object from.
57 | /// An object that specifies the type of service object to get.
58 | /// A service object of type .
59 | /// There is no service of type .
60 | /// or can't be .
61 | public static object GetRequiredService(this IServiceProvider provider, Type serviceType)
62 | {
63 | if (provider == null)
64 | {
65 | throw new ArgumentNullException();
66 | }
67 |
68 | if (serviceType == null)
69 | {
70 | throw new ArgumentNullException();
71 | }
72 |
73 | object service = provider.GetService(serviceType);
74 |
75 | if (service == null)
76 | {
77 | throw new InvalidOperationException();
78 | }
79 |
80 | return service;
81 | }
82 |
83 | ///
84 | /// Creates a new that can be used to resolve scoped services.
85 | ///
86 | /// The to create the scope from.
87 | /// An that can be used to resolve scoped services.
88 | /// can't be .
89 | public static IServiceScope CreateScope(this IServiceProvider provider)
90 | {
91 | if (provider == null)
92 | {
93 | throw new ArgumentNullException();
94 | }
95 |
96 | var service = (ServiceProvider)provider.GetRequiredService(typeof(IServiceProvider));
97 |
98 | return new ServiceScope(service.CreateScope());
99 | }
100 | }
101 | }
--------------------------------------------------------------------------------
/tests/ServiceProviderExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using Microsoft.Extensions.DependencyInjection;
7 | using nanoFramework.TestFramework;
8 | using System;
9 | using System.Collections;
10 |
11 | namespace nanoFramework.DependencyInjection.UnitTests
12 | {
13 | [TestClass]
14 | public class ServiceProviderExtensionsTests
15 | {
16 | [TestMethod]
17 | public void GetServiceReturnsCorrectService()
18 | {
19 | var serviceProvider = CreateTestServiceProvider(1);
20 | var service = serviceProvider.GetService(typeof(IFoo));
21 |
22 | Assert.IsType(typeof(Foo1), service);
23 | }
24 |
25 | [TestMethod]
26 | public void GetRequiredServiceReturnsCorrectService()
27 | {
28 | var serviceProvider = CreateTestServiceProvider(1);
29 | var service = serviceProvider.GetRequiredService(typeof(IFoo));
30 |
31 | Assert.IsType(typeof(Foo1), service);
32 | }
33 |
34 | [TestMethod]
35 | public void GetRequiredServiceThrowsWhenNoServiceRegistered()
36 | {
37 | var serviceProvider = CreateTestServiceProvider(0);
38 |
39 | var expectedMessage = $"No service for type 'nanoFramework.DependencyInjection.UnitTests.ServiceProviderExtensionsTest+IFoo' has been registered.";
40 | Assert.ThrowsException(typeof(InvalidOperationException),
41 | () => serviceProvider.GetRequiredService(typeof(IFoo))
42 | );
43 | }
44 |
45 | [TestMethod]
46 | public void GetServicesReturnsMultipleServices()
47 | {
48 | var serviceProvider = CreateTestServiceProvider(4);
49 |
50 | var types = new Type[] { typeof(IFoo), typeof(IBar) };
51 | object[] services = ((ServiceProvider)serviceProvider).GetService(types);
52 |
53 | Assert.IsType(typeof(Foo1), services[0].GetType());
54 | Assert.IsType(typeof(Foo2), services[1].GetType());
55 | Assert.IsType(typeof(Bar1), services[2].GetType());
56 | Assert.IsType(typeof(Bar2), services[3].GetType());
57 | Assert.AreEqual(4, services.Length);
58 | }
59 |
60 | [TestMethod]
61 | public void GetServicesReturnsAllServices()
62 | {
63 | var serviceProvider = CreateTestServiceProvider(2);
64 | object[] services = serviceProvider.GetServices(typeof(IFoo));
65 |
66 | Assert.IsType(typeof(Foo1), services[0].GetType());
67 | Assert.IsType(typeof(Foo2), services[1].GetType());
68 | Assert.AreEqual(2, services.Length);
69 | }
70 |
71 | [TestMethod]
72 | public void GetServicesReturnsSingleService()
73 | {
74 | var serviceProvider = CreateTestServiceProvider(1);
75 | object[] services = serviceProvider.GetServices(typeof(IFoo));
76 |
77 | Assert.IsType(typeof(Foo1), services[0].GetType());
78 | Assert.AreEqual(1, services.Length);
79 | }
80 |
81 | [TestMethod]
82 | public void GetServicesReturnsCorrectTypes()
83 | {
84 | var serviceProvider = CreateTestServiceProvider(4);
85 | object[] services = serviceProvider.GetServices(typeof(IBar));
86 |
87 | Assert.IsType(typeof(Bar1), services[0].GetType());
88 | Assert.IsType(typeof(Bar2), services[1].GetType());
89 | Assert.AreEqual(2, services.Length);
90 | }
91 |
92 | [TestMethod]
93 | public void GetServicesReturnsEmptyArrayWhenNoServicesAvailable()
94 | {
95 | var serviceProvider = CreateTestServiceProvider(0);
96 | object[] services = serviceProvider.GetServices(typeof(IFoo));
97 |
98 | //Assert.IsType(typeof(object[]), services);
99 | Assert.AreEqual(0, services.Length);
100 | }
101 |
102 | [TestMethod]
103 | public void GetServicesWithBuildServiceProviderReturnsEmptyListWhenNoServicesAvailable()
104 | {
105 | var serviceCollection = new ServiceCollection();
106 | serviceCollection.AddSingleton(typeof(IFoo), new ArrayList());
107 | var serviceProvider = serviceCollection.BuildServiceProvider();
108 |
109 | object[] services = serviceProvider.GetServices(typeof(IBar));
110 |
111 | //Assert.IsType(typeof(object[]), services.GetType());
112 | Assert.AreEqual(0, services.Length);
113 | }
114 |
115 |
116 | private static IServiceProvider CreateTestServiceProvider(int count)
117 | {
118 | var serviceCollection = new ServiceCollection();
119 |
120 | if (count > 0)
121 | {
122 | serviceCollection.AddTransient(typeof(IFoo), typeof(Foo1));
123 | }
124 |
125 | if (count > 1)
126 | {
127 | serviceCollection.AddTransient(typeof(IFoo), typeof(Foo2));
128 | }
129 |
130 | if (count > 2)
131 | {
132 | serviceCollection.AddTransient(typeof(IBar), typeof(Bar1));
133 | }
134 |
135 | if (count > 3)
136 | {
137 | serviceCollection.AddTransient(typeof(IBar), typeof(Bar2));
138 | }
139 |
140 | return serviceCollection.BuildServiceProvider();
141 | }
142 |
143 | public interface IFoo { }
144 |
145 | public class Foo1 : IFoo { }
146 |
147 | public class Foo2 : IFoo { }
148 |
149 | public interface IBar { }
150 |
151 | public class Bar1 : IBar { }
152 |
153 | public class Bar2 : IBar { }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/tests/nanoFramework.DependencyInjection.UnitTests.nfproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildExtensionsPath)\nanoFramework\v1.0\
5 |
6 |
7 |
8 |
9 |
10 |
11 | Debug
12 | AnyCPU
13 | {11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 547a718f-591b-4d7f-a144-8d57c0f98276
15 | Library
16 | Properties
17 | 512
18 | nanoFramework.DependencyInjection.UnitTests
19 | NFUnitTest
20 | False
21 | true
22 | UnitTest
23 | v1.0
24 | true
25 | true
26 |
27 |
28 |
29 | $(MSBuildProjectDirectory)\nano.runsettings
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | ..\packages\nanoFramework.CoreLibrary.1.17.11\lib\mscorlib.dll
76 |
77 |
78 | ..\packages\nanoFramework.TestFramework.3.0.77\lib\nanoFramework.TestFramework.dll
79 |
80 |
81 | ..\packages\nanoFramework.TestFramework.3.0.77\lib\nanoFramework.UnitTestLauncher.exe
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/nanoFramework.DependencyInjection.nfproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | $(MSBuildExtensionsPath)\nanoFramework\v1.0\
6 |
7 |
8 |
9 | Debug
10 | AnyCPU
11 | {11B8DD76-328B-46DF-9F39-F559912D0360};{FAC04EC0-301F-11D3-BF4B-00C04F79EFBC}
12 | {A2B2222C-0553-4877-8CF1-4458B30C0081}
13 | Library
14 | Properties
15 | 512
16 | nanoFramework.DependencyInjection
17 | v1.0
18 | True
19 | bin\$(Configuration)\nanoFramework.DependencyInjection.xml
20 | default
21 | true
22 | true
23 |
24 |
25 | true
26 |
27 |
28 | key.snk
29 |
30 |
31 | false
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | ..\packages\nanoFramework.CoreLibrary.1.17.11\lib\mscorlib.dll
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [**Changes available only in 'Preview' NuGet packages:**](https://github.com/nanoframework/nanoFramework.DependencyInjection/tree/HEAD)
4 |
5 | [Full Changelog](https://github.com/nanoframework/nanoFramework.DependencyInjection/compare/v1.1.1...HEAD)
6 |
7 | **Documentation and other chores:**
8 |
9 | - Update 2 NuGet dependencies [\#34](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/34)
10 |
11 | ## [v1.1.1](https://github.com/nanoframework/nanoFramework.DependencyInjection/tree/v1.1.1) (2023-11-06)
12 |
13 | [Full Changelog](https://github.com/nanoframework/nanoFramework.DependencyInjection/compare/v1.0.35...v1.1.1)
14 |
15 | **Implemented enhancements:**
16 |
17 | - Implemented IServiceProviderIsService [\#33](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/33)
18 |
19 | ## [v1.0.35](https://github.com/nanoframework/nanoFramework.DependencyInjection/tree/v1.0.35) (2023-10-04)
20 |
21 | [Full Changelog](https://github.com/nanoframework/nanoFramework.DependencyInjection/compare/v1.0.22...v1.0.35)
22 |
23 | **Implemented enhancements:**
24 |
25 | - Add support for "Scoped" lifetime [\#31](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/31)
26 | - Instance references aren't stored in ServiceDescriptor if lifetime is Transient [\#30](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/30)
27 |
28 | **Documentation and other chores:**
29 |
30 | - Eliminate deprecated asserts in test cases [\#32](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/32)
31 | - Update 1 NuGet dependencies [\#29](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/29)
32 | - Update 1 NuGet dependencies [\#28](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/28)
33 | - Update 2 NuGet dependencies [\#27](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/27)
34 | - Update 1 NuGet dependencies [\#26](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/26)
35 | - Update 1 NuGet dependencies [\#25](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/25)
36 | - Update 1 NuGet dependencies [\#24](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/24)
37 | - Update 1 NuGet dependencies [\#23](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/23)
38 |
39 | ## [v1.0.22](https://github.com/nanoframework/nanoFramework.DependencyInjection/tree/v1.0.22) (2022-12-23)
40 |
41 | [Full Changelog](https://github.com/nanoframework/nanoFramework.DependencyInjection/compare/v1.0.12...v1.0.22)
42 |
43 | **Documentation and other chores:**
44 |
45 | - Update 2 NuGet dependencies [\#22](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/22)
46 | - Update 1 NuGet dependencies [\#21](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/21)
47 | - Update 1 NuGet dependencies [\#20](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/20)
48 | - Update 1 NuGet dependencies [\#19](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/19)
49 | - Update 1 NuGet dependencies [\#18](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/18)
50 | - Update 1 NuGet dependencies [\#17](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/17)
51 | - Update 1 NuGet dependencies [\#16](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/16)
52 | - Update 1 NuGet dependencies [\#15](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/15)
53 |
54 | ## [v1.0.12](https://github.com/nanoframework/nanoFramework.DependencyInjection/tree/v1.0.12) (2022-10-12)
55 |
56 | [Full Changelog](https://github.com/nanoframework/nanoFramework.DependencyInjection/compare/v1.0.5...v1.0.12)
57 |
58 | **Fixed bugs:**
59 |
60 | - Fixed missing parameters in api footprint [\#14](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/14)
61 |
62 | **Documentation and other chores:**
63 |
64 | - Update 1 NuGet dependencies [\#13](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/13)
65 | - Update 1 NuGet dependencies [\#12](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/12)
66 | - Update 1 NuGet dependencies [\#11](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/11)
67 | - Fix running unit tests locally [\#10](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/10)
68 |
69 | ## [v1.0.5](https://github.com/nanoframework/nanoFramework.DependencyInjection/tree/v1.0.5) (2022-08-04)
70 |
71 | [Full Changelog](https://github.com/nanoframework/nanoFramework.DependencyInjection/compare/v1.0.2...v1.0.5)
72 |
73 | **Implemented enhancements:**
74 |
75 | - Add type checking to constructor parameters [\#9](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/9)
76 |
77 | ## [v1.0.2](https://github.com/nanoframework/nanoFramework.DependencyInjection/tree/v1.0.2) (2022-07-14)
78 |
79 | [Full Changelog](https://github.com/nanoframework/nanoFramework.DependencyInjection/compare/v1.0.0.11...v1.0.2)
80 |
81 | **Implemented enhancements:**
82 |
83 | - Resolved issue where service provider did not dispose correctly [\#8](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/8)
84 |
85 | ## [v1.0.0.11](https://github.com/nanoframework/nanoFramework.DependencyInjection/tree/v1.0.0.11) (2022-06-30)
86 |
87 | [Full Changelog](https://github.com/nanoframework/nanoFramework.DependencyInjection/compare/cd621ea3e1b6198ac9c4fdb42ef082d60ae3d4e1...v1.0.0.11)
88 |
89 | **Implemented enhancements:**
90 |
91 | - Adjusting exceptions and small review [\#3](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/3)
92 |
93 | **Fixed bugs:**
94 |
95 | - Various code fixes [\#6](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/6)
96 |
97 | **Documentation and other chores:**
98 |
99 | - Fixes in code style and comments [\#5](https://github.com/nanoframework/nanoFramework.DependencyInjection/pull/5)
100 |
101 |
102 |
103 | \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
104 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ActivatorUtilities.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 | using System.Reflection;
8 |
9 | namespace Microsoft.Extensions.DependencyInjection
10 | {
11 | ///
12 | /// Helper code for the various activator services.
13 | ///
14 | public static class ActivatorUtilities
15 | {
16 | ///
17 | /// Instantiate a type with constructor arguments provided directly and/or from an .
18 | ///
19 | /// The service provider used to resolve dependencies.
20 | /// The type to activate.
21 | /// Constructor arguments not provided by the .
22 | /// An activated object of type .
23 | /// A suitable constructor for type could not be located. Ensure the type is concrete and all parameters of a public constructor are either registered as services or passed as arguments. Also ensure no extraneous arguments are provided.
24 | public static object CreateInstance(IServiceProvider provider, Type instanceType, params object[] parameters)
25 | {
26 | int bestLength = -1;
27 |
28 | ConstructorMatcher bestMatcher = default;
29 |
30 | if (!instanceType.IsAbstract)
31 | {
32 | foreach (ConstructorInfo constructor in instanceType.GetConstructors())
33 | {
34 | var matcher = new ConstructorMatcher(constructor);
35 | int length = matcher.Match(parameters);
36 |
37 | if (bestLength < length)
38 | {
39 | bestLength = length;
40 | bestMatcher = matcher;
41 | }
42 | }
43 | }
44 |
45 | if (bestLength == -1)
46 | {
47 | throw new InvalidOperationException();
48 | }
49 |
50 | return bestMatcher.CreateInstance(provider);
51 | }
52 |
53 | ///
54 | /// Retrieve an instance of the given type from the service provider. If one is not found then instantiate it directly.
55 | ///
56 | /// The service provider.
57 | /// The type of the service.
58 | /// Constructor arguments not provided by the .
59 | /// The resolved service or created instance.
60 | /// Unable to resolve a service while attempting to activate a constructor.
61 | public static object GetServiceOrCreateInstance(IServiceProvider provider, Type type, params object[] parameters)
62 | {
63 | return provider.GetService(type) ?? CreateInstance(provider, type, parameters);
64 | }
65 |
66 | private struct ConstructorMatcher
67 | {
68 | private readonly object[] _parameterValues;
69 | private readonly ParameterInfo[] _parameters;
70 | private readonly ConstructorInfo _constructor;
71 |
72 | public ConstructorMatcher(ConstructorInfo constructor)
73 | {
74 | _constructor = constructor;
75 | _parameters = _constructor.GetParameters();
76 | _parameterValues = new object[_parameters.Length];
77 | }
78 |
79 | public int Match(object[] givenParameters)
80 | {
81 | int applyIndexStart = 0;
82 | int applyExactLength = 0;
83 |
84 | for (int givenIndex = 0; givenIndex != givenParameters.Length; givenIndex++)
85 | {
86 | Type givenType = givenParameters[givenIndex].GetType();
87 | bool givenMatched = false;
88 |
89 | for (int applyIndex = applyIndexStart; !givenMatched && applyIndex != _parameters.Length; ++applyIndex)
90 | {
91 | if (_parameterValues[applyIndex] == null
92 | && _parameters[applyIndex].ParameterType.Equals(givenType))
93 | {
94 | givenMatched = true;
95 | _parameterValues[applyIndex] = givenParameters[givenIndex];
96 |
97 | if (applyIndexStart == applyIndex)
98 | {
99 | applyIndexStart++;
100 |
101 | if (applyIndex == givenIndex)
102 | {
103 | applyExactLength = applyIndex;
104 | }
105 | }
106 | }
107 | }
108 |
109 | if (!givenMatched)
110 | {
111 | return -1;
112 | }
113 | }
114 | return applyExactLength;
115 | }
116 |
117 | public object CreateInstance(IServiceProvider provider)
118 | {
119 | for (int index = 0; index != _parameters.Length; index++)
120 | {
121 | if (_parameterValues[index] == null)
122 | {
123 | object value = provider.GetService(_parameters[index].ParameterType);
124 |
125 | if (value == null)
126 | {
127 | throw new InvalidOperationException($"'{_parameters[index].ParameterType}'->'{_constructor.DeclaringType}'.");
128 | }
129 | else
130 | {
131 | _parameterValues[index] = value;
132 | }
133 | }
134 | }
135 |
136 | return _constructor.Invoke(_parameterValues);
137 | }
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/System/AggregateException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System.Collections;
7 | using System.Diagnostics;
8 |
9 | namespace System
10 | {
11 | /// Initializes a new instance of the class with a system-supplied message that describes the error.
12 | ///
13 | /// is used to consolidate multiple failures into a single, throwable
14 | /// exception object.
15 | ///
16 | [Serializable]
17 | [DebuggerDisplay("Count = {InnerExceptionCount}")]
18 | public class AggregateException : Exception
19 | {
20 | private readonly Exception[] _innerExceptions;
21 | private static readonly string _defaultMessage = "One or more errors occurred.";
22 |
23 | ///
24 | /// Initializes a new instance of the class.
25 | ///
26 | public AggregateException()
27 | : this(_defaultMessage)
28 | {
29 | }
30 |
31 | ///
32 | /// Initializes a new instance of the class with
33 | /// a specified error message.
34 | ///
35 | /// The error message that explains the reason for the exception.
36 | public AggregateException(string message)
37 | : base(message)
38 | {
39 | _innerExceptions = new Exception[0];
40 | }
41 |
42 | ///
43 | /// Initializes a new instance of the class with
44 | /// a specified error message.
45 | ///
46 | /// The error message that explains the reason for the exception.
47 | /// The exceptions that are the cause of the current exception.
48 | /// One of the is .
49 | public AggregateException(string message, params Exception[] innerException)
50 | : base(message)
51 | {
52 | foreach(Exception ex in innerException)
53 | {
54 | if (ex == null)
55 | {
56 | throw new ArgumentNullException();
57 | }
58 | }
59 |
60 | _innerExceptions = innerException;
61 | }
62 |
63 | ///
64 | /// Initializes a new instance of the class with
65 | /// a specified error message.
66 | ///
67 | /// The error message that explains the reason for the exception.
68 | /// An array list of object exceptions that is the cause of the current exception.
69 | /// An element of innerExceptions not of Exception type.
70 | /// One of the is .
71 | public AggregateException(string message, ArrayList innerException)
72 | : base(message)
73 | {
74 | foreach (Exception ex in innerException)
75 | {
76 | if (ex == null)
77 | {
78 | throw new ArgumentNullException();
79 | }
80 | }
81 |
82 | try
83 | {
84 | _innerExceptions = (Exception[])innerException.ToArray(typeof(Exception));
85 | }
86 | catch
87 | {
88 | throw new ArgumentException();
89 | }
90 | }
91 |
92 | ///
93 | /// Gets an of the exception instances that caused the current exception.
94 | ///
95 | public ArrayList InnerExceptions
96 | {
97 | get
98 | {
99 | var execptions = new ArrayList();
100 | foreach(Exception ex in _innerExceptions)
101 | {
102 | execptions.Add(ex);
103 | }
104 |
105 | return execptions;
106 | }
107 | }
108 |
109 | ///
110 | /// Gets a message that describes the exception.
111 | ///
112 | public override string Message
113 | {
114 | get
115 | {
116 | if (_innerExceptions.Length == 0)
117 | {
118 | return base.Message;
119 | }
120 |
121 | var msg = $"{ base.Message } ";
122 |
123 | var count = _innerExceptions.Length;
124 | for (int index = 0; index < count; index++)
125 | {
126 | if (index < count - 1)
127 | {
128 | msg = string.Concat(msg, $"({ _innerExceptions[index].Message }) ");
129 | }
130 | else
131 | {
132 | msg = string.Concat(msg, $"({ _innerExceptions[index].Message })");
133 | }
134 | }
135 |
136 | return msg;
137 | }
138 | }
139 |
140 | ///
141 | /// Creates and returns a string representation of the current .
142 | ///
143 | /// A string representation of the current exception.
144 | public override string ToString()
145 | {
146 | string msg = base.ToString();
147 |
148 | for (int index = 0; index < _innerExceptions.Length; index++)
149 | {
150 | if (index == 0)
151 | {
152 | msg = string.Concat(msg, "\n");
153 | }
154 |
155 | if (_innerExceptions[index] == InnerException)
156 | {
157 | // Already logged in base.ToString()
158 | continue;
159 | }
160 |
161 | msg = string.Concat(msg, $"---> (Inner Exception #{index}) {_innerExceptions[index]} <---\n");
162 | }
163 |
164 | return msg;
165 | }
166 |
167 | internal int InnerExceptionCount => _innerExceptions.Length;
168 | }
169 | }
--------------------------------------------------------------------------------
/tests/ServiceCollectionDescriptorExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Extensions.DependencyInjection;
3 | using nanoFramework.DependencyInjection.UnitTests.Fakes;
4 | using nanoFramework.TestFramework;
5 |
6 | // ReSharper disable InvokeAsExtensionMethod
7 | namespace nanoFramework.DependencyInjection.UnitTests
8 | {
9 | [TestClass]
10 | public class ServiceCollectionDescriptorExtensionsTests
11 | {
12 | private static ServiceDescriptor CreateSingletonServiceDescriptor() => ServiceDescriptor.Singleton(typeof(IService1), typeof(Service1));
13 | private static ServiceDescriptor CreateTransientServiceDescriptor() => ServiceDescriptor.Transient(typeof(IService1), typeof(Service1));
14 |
15 | [TestMethod]
16 | public void Add_adds_descriptor()
17 | {
18 | var descriptor = CreateSingletonServiceDescriptor();
19 |
20 | var collection = new ServiceCollection();
21 |
22 | ServiceCollectionDescriptorExtensions.Add(collection, descriptor);
23 |
24 | Assert.AreEqual(1, collection.Count);
25 | Assert.IsTrue(collection.Contains(descriptor));
26 | }
27 |
28 | [TestMethod]
29 | public void Add_adds_descriptors()
30 | {
31 | var singletonDescriptor = CreateSingletonServiceDescriptor();
32 | var transientDescriptor = CreateTransientServiceDescriptor();
33 | var descriptors = new[] { singletonDescriptor, transientDescriptor };
34 |
35 | var collection = new ServiceCollection();
36 |
37 | ServiceCollectionDescriptorExtensions.Add(collection, descriptors);
38 |
39 | Assert.AreEqual(2, collection.Count);
40 | Assert.IsTrue(collection.Contains(singletonDescriptor));
41 | Assert.IsTrue(collection.Contains(transientDescriptor));
42 | }
43 |
44 | [TestMethod]
45 | public void Add_throws_when_collection_is_null()
46 | {
47 | var test = new object[]{};
48 | Assert.ThrowsException(typeof(ArgumentNullException), () => ServiceCollectionDescriptorExtensions.Add(null!, CreateSingletonServiceDescriptor()));
49 | Assert.ThrowsException(typeof(ArgumentNullException), () => ServiceCollectionDescriptorExtensions.Add(null!, new ServiceDescriptor[]{}));
50 | }
51 |
52 | [TestMethod]
53 | public void Add_throws_when_descriptor_is_null()
54 | {
55 | Assert.ThrowsException(typeof(ArgumentNullException), () => ServiceCollectionDescriptorExtensions.Add(new ServiceCollection(), ((ServiceDescriptor)null)!));
56 | }
57 |
58 | [TestMethod]
59 | public void Add_throws_when_descriptors_contains_invalid_type()
60 | {
61 | var descriptors = new[]
62 | {
63 | CreateSingletonServiceDescriptor(),
64 | CreateTransientServiceDescriptor(),
65 | new object()
66 | };
67 |
68 | Assert.ThrowsException(typeof(ArgumentException), () => ServiceCollectionDescriptorExtensions.Add(new ServiceCollection(), descriptors));
69 | }
70 |
71 | [TestMethod]
72 | public void Add_throws_when_descriptors_is_null()
73 | {
74 | Assert.ThrowsException(typeof(ArgumentNullException), () => ServiceCollectionDescriptorExtensions.Add(new ServiceCollection(), ((ServiceDescriptor[])null)!));
75 | }
76 |
77 | [TestMethod]
78 | public void RemoveAll_removes_descriptors()
79 | {
80 | var serviceA = ServiceDescriptor.Scoped(typeof(IService1), typeof(Service1));
81 | var serviceB = ServiceDescriptor.Singleton(typeof(IService1), typeof(Service1));
82 | var serviceC = ServiceDescriptor.Transient(typeof(IService1), typeof(Service1));
83 | var serviceD = ServiceDescriptor.Singleton(typeof(IService2), typeof(Service2));
84 |
85 | var collection = new ServiceCollection();
86 |
87 | collection.Add(serviceA);
88 | collection.Add(serviceB);
89 | collection.Add(serviceC);
90 | collection.Add(serviceD);
91 |
92 | Assert.AreEqual(4, collection.Count);
93 | Assert.IsTrue(collection.Contains(serviceA));
94 | Assert.IsTrue(collection.Contains(serviceB));
95 | Assert.IsTrue(collection.Contains(serviceC));
96 | Assert.IsTrue(collection.Contains(serviceD));
97 |
98 | ServiceCollectionDescriptorExtensions.RemoveAll(collection, typeof(IService1));
99 |
100 | Assert.AreEqual(1, collection.Count);
101 | Assert.IsFalse(collection.Contains(serviceA));
102 | Assert.IsFalse(collection.Contains(serviceB));
103 | Assert.IsFalse(collection.Contains(serviceC));
104 | Assert.IsTrue(collection.Contains(serviceD));
105 | }
106 |
107 | [TestMethod]
108 | public void RemoveAll_throws_when_collection_is_null()
109 | {
110 | Assert.ThrowsException(typeof(ArgumentNullException), () => ServiceCollectionDescriptorExtensions.RemoveAll(null!, typeof(IService1)));
111 | }
112 |
113 | [TestMethod]
114 | public void RemoveAll_throws_when_serviceType_is_null()
115 | {
116 | Assert.ThrowsException(typeof(ArgumentNullException), () => ServiceCollectionDescriptorExtensions.RemoveAll(new ServiceCollection(), null!));
117 | }
118 |
119 | [TestMethod]
120 | public void Replace_replaces_descriptor()
121 | {
122 | var singletonDescriptor = CreateSingletonServiceDescriptor();
123 | var transientDescriptor = CreateTransientServiceDescriptor();
124 | var otherDescriptor = ServiceDescriptor.Singleton(typeof(IService2), typeof(Service2));
125 |
126 | var collection = new ServiceCollection();
127 |
128 | collection.Add(singletonDescriptor);
129 | collection.Add(otherDescriptor);
130 |
131 | Assert.AreEqual(2, collection.Count);
132 | Assert.IsTrue(collection.Contains(singletonDescriptor));
133 | Assert.IsFalse(collection.Contains(transientDescriptor));
134 | Assert.IsTrue(collection.Contains(otherDescriptor));
135 |
136 | ServiceCollectionDescriptorExtensions.Replace(collection, transientDescriptor);
137 |
138 | Assert.AreEqual(2, collection.Count);
139 | Assert.IsFalse(collection.Contains(singletonDescriptor));
140 | Assert.IsTrue(collection.Contains(transientDescriptor));
141 | Assert.IsTrue(collection.Contains(otherDescriptor));
142 | }
143 |
144 | [TestMethod]
145 | public void Replace_throws_when_collection_is_null()
146 | {
147 | Assert.ThrowsException(typeof(ArgumentNullException), () => ServiceCollectionDescriptorExtensions.Replace(null!, CreateSingletonServiceDescriptor()));
148 | }
149 |
150 | [TestMethod]
151 | public void Replace_throws_when_descriptor_is_null()
152 | {
153 | Assert.ThrowsException(typeof(ArgumentNullException), () => ServiceCollectionDescriptorExtensions.Replace(new ServiceCollection(), null!));
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
364 |
365 | #Sonarcloud
366 | .sonarqube
367 |
368 | #VS Code
369 | .vscode
370 |
--------------------------------------------------------------------------------
/tests/ActivatorUtilitiesTests.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 | using nanoFramework.TestFramework;
8 | using nanoFramework.DependencyInjection.UnitTests.Fakes;
9 | using Microsoft.Extensions.DependencyInjection;
10 |
11 | namespace nanoFramework.DependencyInjection.UnitTests
12 | {
13 | [TestClass]
14 | public class ActivatorUtilitiesTests
15 | {
16 | [TestMethod]
17 | public void TypeActivatorEnablesYouToCreateAnyTypeWithServicesEvenWhenNotInIocContainer()
18 | {
19 | var serviceProvider = new ServiceCollection()
20 | .AddTransient(typeof(IFakeService), typeof(FakeService))
21 | .BuildServiceProvider();
22 |
23 | var instance = (AnotherClass)ActivatorUtilities.CreateInstance(serviceProvider, typeof(AnotherClass));
24 |
25 | Assert.IsNotNull(instance.FakeService);
26 | }
27 |
28 |
29 | [TestMethod]
30 | public void TypeActivatorAcceptsAnyNumberOfAdditionalConstructorParametersToProvide()
31 | {
32 | var serviceProvider = new ServiceCollection()
33 | .AddTransient(typeof(IFakeService), typeof(FakeService))
34 | .BuildServiceProvider();
35 |
36 | var instance = (AnotherClassAcceptingData)ActivatorUtilities.CreateInstance(
37 | serviceProvider,
38 | typeof(AnotherClassAcceptingData),
39 | "1",
40 | "2");
41 |
42 | Assert.IsNotNull(instance.FakeService);
43 | Assert.AreEqual("1", instance.One);
44 | Assert.AreEqual("2", instance.Two);
45 | }
46 |
47 | [TestMethod]
48 | public void TypeActivatorCanDisambiguateConstructorsWithUniqueArguments()
49 | {
50 | var serviceProvider = new ServiceCollection()
51 | .AddTransient(typeof(IFakeService), typeof(FakeService))
52 | .BuildServiceProvider();
53 |
54 | var instance = (ClassWithAmbiguousCtors)ActivatorUtilities.CreateInstance(serviceProvider, typeof(ClassWithAmbiguousCtors), "1", 2);
55 |
56 | Assert.IsNotNull(instance);
57 | Assert.IsNotNull(instance.FakeService);
58 | Assert.AreEqual("1", instance.Data1);
59 | Assert.AreEqual(2, instance.Data2);
60 | }
61 |
62 | [TestMethod]
63 | [DataRow("", "string")]
64 | [DataRow(5, "IFakeService, int")]
65 | public void TypeActivatorCreateInstanceUsesFirstMathchedConstructor(object value, string ctor)
66 | {
67 | var serviceProvider = new ServiceCollection()
68 | .AddTransient(typeof(IFakeService), typeof(FakeService))
69 | .BuildServiceProvider();
70 |
71 | var instance = (ClassWithAmbiguousCtors)ActivatorUtilities.CreateInstance(serviceProvider, typeof(ClassWithAmbiguousCtors), value);
72 |
73 | Assert.AreEqual(ctor, instance.CtorUsed);
74 | }
75 |
76 | [TestMethod]
77 | public void TypeActivatorRethrowsOriginalExceptionFromConstructor()
78 | {
79 | Assert.ThrowsException(typeof(Exception),
80 | () =>
81 | {
82 | try
83 | {
84 | ActivatorUtilities.CreateInstance(null, typeof(ClassWithThrowingCtor), new object[] { new FakeService() });
85 | }
86 | catch (Exception ex)
87 | {
88 | if (string.Equals(nameof(ClassWithThrowingCtor), ex.Message))
89 | {
90 | throw new Exception();
91 | }
92 | else
93 | {
94 | throw new NullReferenceException();
95 | }
96 | }
97 | }
98 | );
99 |
100 | Assert.ThrowsException(typeof(Exception),
101 | () =>
102 | {
103 | try
104 | {
105 | ActivatorUtilities.CreateInstance(null, typeof(ClassWithThrowingEmptyCtor));
106 | }
107 | catch (Exception ex)
108 | {
109 | if (string.Equals(nameof(ClassWithThrowingEmptyCtor), ex.Message))
110 | {
111 | throw new Exception();
112 | }
113 | else
114 | {
115 | throw new NullReferenceException();
116 | }
117 | }
118 | }
119 | );
120 | }
121 |
122 | [TestMethod]
123 | public void TypeActivatorRequiresAllArgumentsCanBeAccepted()
124 | {
125 | var serviceProvider = new ServiceCollection()
126 | .AddTransient(typeof(IFakeService), typeof(FakeService))
127 | .BuildServiceProvider();
128 |
129 | Assert.ThrowsException(typeof(InvalidOperationException),
130 | () => ActivatorUtilities.CreateInstance(serviceProvider, typeof(AnotherClassAcceptingData), "1", "2", "3")
131 | );
132 |
133 | Assert.ThrowsException(typeof(InvalidOperationException),
134 | () => ActivatorUtilities.CreateInstance(serviceProvider, typeof(AnotherClassAcceptingData), 1, 2)
135 | );
136 | }
137 |
138 | [TestMethod]
139 | public void GetServiceOrCreateInstanceRegisteredServiceTransient()
140 | {
141 | // Reset the count because test order is not guaranteed
142 | lock (CreationCountFakeService.InstanceLock)
143 | {
144 | CreationCountFakeService.InstanceCount = 0;
145 |
146 | var serviceProvider = new ServiceCollection()
147 | .AddTransient(typeof(IFakeService), typeof(FakeService))
148 | .AddTransient(typeof(CreationCountFakeService))
149 | .BuildServiceProvider();
150 |
151 | var service = (CreationCountFakeService)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, typeof(CreationCountFakeService));
152 | Assert.IsNotNull(service);
153 | Assert.AreEqual(1, service.InstanceId);
154 | Assert.AreEqual(1, CreationCountFakeService.InstanceCount);
155 |
156 | service = (CreationCountFakeService)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, typeof(CreationCountFakeService));
157 | Assert.IsNotNull(service);
158 | Assert.AreEqual(2, service.InstanceId);
159 | Assert.AreEqual(2, CreationCountFakeService.InstanceCount);
160 | }
161 | }
162 |
163 | [TestMethod]
164 | public void GetServiceOrCreateInstanceRegisteredServiceSingleton()
165 | {
166 | // Reset the count because test order is not guaranteed
167 | lock (CreationCountFakeService.InstanceLock)
168 | {
169 | CreationCountFakeService.InstanceCount = 0;
170 |
171 | var serviceProvider = new ServiceCollection()
172 | .AddTransient(typeof(IFakeService), typeof(FakeService))
173 | .AddSingleton(typeof(CreationCountFakeService))
174 | .BuildServiceProvider();
175 |
176 | var service = (CreationCountFakeService)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, typeof(CreationCountFakeService));
177 | Assert.IsNotNull(service);
178 | Assert.AreEqual(1, service.InstanceId);
179 | Assert.AreEqual(1, CreationCountFakeService.InstanceCount);
180 |
181 | service = (CreationCountFakeService)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, typeof(CreationCountFakeService));
182 | Assert.IsNotNull(service);
183 | Assert.AreEqual(1, service.InstanceId);
184 | Assert.AreEqual(1, CreationCountFakeService.InstanceCount);
185 | }
186 | }
187 |
188 | [TestMethod]
189 | public void GetServiceOrCreateInstanceUnregisteredService()
190 | {
191 | // Reset the count because test order is not guaranteed
192 | lock (CreationCountFakeService.InstanceLock)
193 | {
194 | CreationCountFakeService.InstanceCount = 0;
195 |
196 | var serviceProvider = new ServiceCollection()
197 | .AddTransient(typeof(IFakeService), typeof(FakeService))
198 | .BuildServiceProvider();
199 |
200 | var service = (CreationCountFakeService)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, typeof(CreationCountFakeService));
201 | Assert.IsNotNull(service);
202 | Assert.AreEqual(1, service.InstanceId);
203 | Assert.AreEqual(1, CreationCountFakeService.InstanceCount);
204 |
205 | service = (CreationCountFakeService)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, typeof(CreationCountFakeService));
206 | Assert.IsNotNull(service);
207 | Assert.AreEqual(2, service.InstanceId);
208 | Assert.AreEqual(2, CreationCountFakeService.InstanceCount);
209 | }
210 | }
211 |
212 | [TestMethod]
213 | public void UnRegisteredServiceAsConstructorParameterThrowsException()
214 | {
215 | var serviceProvider = new ServiceCollection()
216 | .AddSingleton(typeof(CreationCountFakeService))
217 | .BuildServiceProvider();
218 |
219 | Assert.ThrowsException(typeof(InvalidOperationException),
220 | () => ActivatorUtilities.CreateInstance(serviceProvider, typeof(CreationCountFakeService))
221 | );
222 | }
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/tests/ServiceCollectionTests.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using Microsoft.Extensions.DependencyInjection;
7 | using nanoFramework.DependencyInjection.UnitTests.Fakes;
8 | using nanoFramework.TestFramework;
9 | using System;
10 | using System.Collections;
11 |
12 | namespace nanoFramework.DependencyInjection.UnitTests
13 | {
14 | [TestClass]
15 | public class ServiceCollectionTests
16 | {
17 | [TestMethod]
18 | public static void ServiceDescriptorDescribe()
19 | {
20 | var serviceDescriptor = ServiceDescriptor.Describe(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Singleton);
21 |
22 | Assert.IsInstanceOfType(serviceDescriptor.ServiceType, typeof(IFakeObject));
23 | Assert.IsInstanceOfType(serviceDescriptor.ImplementationType, typeof(FakeObject));
24 | Assert.IsTrue(serviceDescriptor.Lifetime == ServiceLifetime.Singleton);
25 | }
26 |
27 | [TestMethod]
28 | public static void ServiceDescriptorToString()
29 | {
30 | var expectedMessage = "ServiceType: nanoFramework.DependencyInjection.UnitTests.Fakes.IFakeObject Lifetime: 0 ImplementationType: nanoFramework.DependencyInjection.UnitTests.Fakes.FakeObject.";
31 | var serviceDescriptor = new ServiceDescriptor(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Singleton);
32 |
33 | Assert.IsInstanceOfType(serviceDescriptor.ServiceType, typeof(IFakeObject));
34 | Assert.IsInstanceOfType(serviceDescriptor.ImplementationType, typeof(FakeObject));
35 | Assert.IsTrue(serviceDescriptor.Lifetime == ServiceLifetime.Singleton);
36 | Assert.Contains(serviceDescriptor.ToString(), expectedMessage);
37 | }
38 |
39 | [TestMethod]
40 | public static void ServiceCollectionAdd()
41 | {
42 | var serviceCollection = new ServiceCollection();
43 | var serviceDescriptor = new ServiceDescriptor(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Singleton);
44 |
45 | serviceCollection.Add(serviceDescriptor);
46 | Assert.AreEqual(1, serviceCollection.Count);
47 |
48 | Assert.IsInstanceOfType(serviceCollection[0].ServiceType, typeof(IFakeObject));
49 | Assert.IsInstanceOfType(serviceCollection[0].ImplementationType, typeof(FakeObject));
50 | Assert.IsTrue(serviceCollection[0].Lifetime == ServiceLifetime.Singleton);
51 | }
52 |
53 | [TestMethod]
54 | public static void ServiceCollectionReplace()
55 | {
56 | var serviceCollection = new ServiceCollection();
57 | var serviceDescriptor = new ServiceDescriptor(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Singleton);
58 |
59 | serviceCollection.Add(serviceDescriptor);
60 | Assert.AreEqual(1, serviceCollection.Count);
61 |
62 | Assert.IsInstanceOfType(serviceCollection[0].ServiceType, typeof(IFakeObject));
63 | Assert.IsInstanceOfType(serviceCollection[0].ImplementationType, typeof(FakeObject));
64 | Assert.IsTrue(serviceCollection[0].Lifetime == ServiceLifetime.Singleton);
65 |
66 | serviceDescriptor = new ServiceDescriptor(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Transient);
67 |
68 | serviceCollection.Replace(serviceDescriptor);
69 | Assert.AreEqual(1, serviceCollection.Count);
70 |
71 | Assert.IsInstanceOfType(serviceCollection[0].ServiceType, typeof(IFakeObject));
72 | Assert.IsInstanceOfType(serviceCollection[0].ImplementationType, typeof(FakeObject));
73 | Assert.IsTrue(serviceCollection[0].Lifetime == ServiceLifetime.Transient);
74 | }
75 |
76 | [TestMethod]
77 | public static void ServiceCollectionAddSingleton()
78 | {
79 | var serviceCollection = new ServiceCollection();
80 |
81 | serviceCollection.AddSingleton(typeof(IFakeObject), typeof(FakeObject));
82 | Assert.IsTrue(serviceCollection[0].Lifetime == ServiceLifetime.Singleton);
83 | }
84 |
85 | [TestMethod]
86 | public static void ServiceCollectionAddTransient()
87 | {
88 | var serviceCollection = new ServiceCollection();
89 |
90 | serviceCollection.AddTransient(typeof(IFakeObject), typeof(FakeObject));
91 | Assert.IsTrue(serviceCollection[0].Lifetime == ServiceLifetime.Transient);
92 | }
93 |
94 | [TestMethod]
95 | public static void ServiceCollectionTryAdd()
96 | {
97 | var serviceCollection = new ServiceCollection();
98 | var serviceDescriptor = new ServiceDescriptor(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Transient);
99 |
100 | serviceCollection.TryAdd(serviceDescriptor);
101 | serviceCollection.TryAdd(serviceDescriptor);
102 | Assert.AreEqual(1, serviceCollection.Count);
103 |
104 | Assert.IsTrue(serviceCollection[0].Lifetime == ServiceLifetime.Transient);
105 | }
106 |
107 | [TestMethod]
108 | public static void ServiceCollectionTryAddEnumerable()
109 | {
110 | var serviceCollection = new ServiceCollection();
111 | var serviceDescriptor = new ServiceDescriptor(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Transient);
112 |
113 | serviceCollection.TryAddEnumerable(serviceDescriptor);
114 | Assert.AreEqual(1, serviceCollection.Count);
115 |
116 | var serviceDescriptors = new ArrayList
117 | {
118 | new ServiceDescriptor(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Transient),
119 | new ServiceDescriptor(typeof(IFakeService), typeof(FakeService), ServiceLifetime.Singleton),
120 | new ServiceDescriptor(typeof(IFakeService), typeof(FakeService), ServiceLifetime.Singleton)
121 | };
122 |
123 | serviceCollection.TryAddEnumerable(serviceDescriptors);
124 | Assert.AreEqual(2, serviceCollection.Count);
125 | }
126 |
127 | [TestMethod]
128 | public static void ServiceCollectionInterfaceThrowsArgumentException()
129 | {
130 | var serviceCollection = new ServiceCollection();
131 |
132 | Assert.ThrowsException(typeof(ArgumentException),
133 | () => serviceCollection.AddSingleton(typeof(IFakeObject), typeof(IFakeObject))
134 | );
135 | }
136 |
137 | [TestMethod]
138 | public static void ServiceCollectionRemove()
139 | {
140 | var serviceCollection = new ServiceCollection();
141 | var serviceDescriptor = ServiceDescriptor.Describe(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Transient);
142 |
143 | serviceCollection.Add(serviceDescriptor);
144 | Assert.AreEqual(1, serviceCollection.Count);
145 |
146 | serviceCollection.Remove(serviceDescriptor);
147 | Assert.IsTrue(serviceCollection.Count == 0);
148 | }
149 |
150 | [TestMethod]
151 | public static void ServiceCollectionRemoveAll()
152 | {
153 | var serviceCollection = new ServiceCollection();
154 |
155 | serviceCollection.AddTransient(typeof(IFakeObject), typeof(FakeObject));
156 | serviceCollection.AddSingleton(typeof(IFakeObject), typeof(FakeObject));
157 | serviceCollection.AddSingleton(typeof(IFakeService), typeof(FakeService));
158 | Assert.AreEqual(3, serviceCollection.Count);
159 |
160 | serviceCollection.RemoveAll(typeof(IFakeObject));
161 | Assert.AreEqual(1, serviceCollection.Count);
162 |
163 | Assert.IsInstanceOfType(serviceCollection[0].ServiceType, typeof(IFakeService));
164 | Assert.IsInstanceOfType(serviceCollection[0].ImplementationType, typeof(FakeService));
165 | Assert.IsTrue(serviceCollection[0].Lifetime == ServiceLifetime.Singleton);
166 | }
167 |
168 | [TestMethod]
169 | public static void ServiceCollectionRemoveAt()
170 | {
171 | var serviceCollection = new ServiceCollection();
172 |
173 | serviceCollection.AddTransient(typeof(IFakeObject), typeof(FakeObject));
174 | serviceCollection.AddSingleton(typeof(IFakeObject), typeof(FakeObject));
175 | serviceCollection.AddSingleton(typeof(IFakeService), typeof(FakeService));
176 | Assert.AreEqual(3, serviceCollection.Count);
177 |
178 | serviceCollection.RemoveAt(1);
179 | Assert.AreEqual(2, serviceCollection.Count);
180 |
181 | Assert.IsInstanceOfType(serviceCollection[0].ServiceType, typeof(IFakeObject));
182 | Assert.IsInstanceOfType(serviceCollection[0].ImplementationType, typeof(FakeObject));
183 | Assert.IsTrue(serviceCollection[0].Lifetime == ServiceLifetime.Transient);
184 | Assert.IsInstanceOfType(serviceCollection[1].ServiceType, typeof(IFakeService));
185 | Assert.IsInstanceOfType(serviceCollection[1].ImplementationType, typeof(FakeService));
186 | Assert.IsTrue(serviceCollection[1].Lifetime == ServiceLifetime.Singleton);
187 | }
188 |
189 | [TestMethod]
190 | public static void ServiceCollectionInsert()
191 | {
192 | var serviceCollection = new ServiceCollection();
193 | var serviceDescriptor1 = ServiceDescriptor.Describe(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Transient);
194 | var serviceDescriptor2 = ServiceDescriptor.Describe(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Singleton);
195 | var serviceDescriptor3 = ServiceDescriptor.Describe(typeof(IFakeService), typeof(FakeService), ServiceLifetime.Singleton);
196 |
197 | serviceCollection.Add(serviceDescriptor1);
198 | serviceCollection.Add(serviceDescriptor2);
199 | serviceCollection.Insert(0, serviceDescriptor3);
200 | Assert.AreEqual(3, serviceCollection.Count);
201 |
202 | Assert.IsInstanceOfType(serviceCollection[0].ServiceType, typeof(IFakeService));
203 | Assert.IsInstanceOfType(serviceCollection[0].ImplementationType, typeof(FakeService));
204 | Assert.IsTrue(serviceCollection[0].Lifetime == ServiceLifetime.Singleton);
205 | }
206 |
207 | [TestMethod]
208 | public static void ServiceCollectionContains()
209 | {
210 | var serviceCollection = new ServiceCollection();
211 | var serviceDescriptor1 = ServiceDescriptor.Describe(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Transient);
212 | var serviceDescriptor2 = ServiceDescriptor.Describe(typeof(IFakeObject), typeof(FakeObject), ServiceLifetime.Singleton);
213 |
214 | serviceCollection.Add(serviceDescriptor1);
215 | Assert.AreEqual(1, serviceCollection.Count);
216 |
217 | Assert.IsTrue(serviceCollection.Contains(serviceDescriptor1));
218 | Assert.IsFalse(serviceCollection.Contains(serviceDescriptor2));
219 | }
220 | }
221 | }
222 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://sonarcloud.io/dashboard?id=nanoframework_nanoFramework.DependencyInjection) [](https://sonarcloud.io/dashboard?id=nanoframework_nanoFramework.DependencyInjection) [](LICENSE) [](https://www.nuget.org/packages/nanoFramework.DependencyInjection/) [](https://github.com/nanoframework/Home/blob/main/CONTRIBUTING.md) [](https://discord.gg/gCyBu8T)
2 |
3 | 
4 |
5 | -----
6 |
7 | # Welcome to the .NET nanoFramework Dependency Injection Library repository
8 |
9 | Provides Dependency Injection (DI) for Inversion of Control (IoC) between classes and their dependencies built for .NET nanoFramework.
10 |
11 | ## Build status
12 |
13 | | Component | Build Status | NuGet Package |
14 | |:-|---|---|
15 | | nanoFramework.DependencyInjection | [](https://dev.azure.com/nanoframework/nanoFramework.DependencyInjection/_build/latest?definitionId=95&branchName=main) | [](https://www.nuget.org/packages/nanoFramework.DependencyInjection/) |
16 |
17 | ## Samples
18 |
19 | [Dependency Injection Samples](https://github.com/nanoframework/Samples/tree/main/samples/DependencyInjection)
20 |
21 | [Dependency Injection Unit Tests](https://github.com/nanoframework/nanoFramework.DependencyInjection/tree/main/tests)
22 |
23 | ## Dependency Injection Container
24 |
25 | 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.
26 |
27 | This API mirrors as close as possible the official .NET [DependencyInjection](https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection). Exceptions are mainly derived from the lack of generics support in .NET nanoFramework.
28 |
29 | The .NET nanoFramework [Generic Host](https://github.com/nanoframework/nanoFramework.Hosting) provides convenience methods for creating dependency injection (DI) application containers with preconfigured defaults.
30 |
31 | ## Usage
32 |
33 | ### Service Collection
34 |
35 | Creating a dependency injection container required three basic components.
36 |
37 | - Object Composition - A object composition defining a set of objects to create and couple.
38 | - Registering Services - Define an instance of the ServiceCollection and register the object composition with a specific service lifetime.
39 | - Service Provider - Creating a service provider to retrieve the object.
40 |
41 | ### Object Composition
42 |
43 | Define an object composition to create and couple.
44 |
45 | 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.
46 |
47 | ```csharp
48 | public class RootObject
49 | {
50 | public int One { get; }
51 |
52 | public string Two { get; }
53 |
54 | public ServiceObject ServiceObject { get; protected set; }
55 |
56 | public RootObject(ServiceObject serviceObject)
57 | {
58 | ServiceObject = serviceObject;
59 | }
60 |
61 | // constructor with the most parameters will be used for activation
62 | public RootObject(ServiceObject serviceObject, int one, string two)
63 | {
64 | ServiceObject = serviceObject;
65 | One = one;
66 | Two = two;
67 | }
68 | }
69 |
70 | public class ServiceObject
71 | {
72 | public string Three { get; set; }
73 | }
74 | ```
75 |
76 | ### Registering Services
77 |
78 | Create a Service Collection and register singleton or transient type services to the collection.
79 |
80 | ```csharp
81 | var serviceProvider = new ServiceCollection()
82 | .AddSingleton(typeof(ServiceObject))
83 | .AddSingleton(typeof(RootObject))
84 | .BuildServiceProvider();
85 | ```
86 | ### Service Provider
87 |
88 | Create a Service Provider to access or update an object.
89 |
90 | ```csharp
91 | var service = (RootObject)serviceProvider.GetService(typeof(RootObject));
92 | service.ServiceObject.Three = "3";
93 | ```
94 |
95 | Create a scoped Service Provider providing convient access to crate and distroy scoped object.
96 |
97 | ```csharp
98 | var serviceProvider = new ServiceCollection()
99 | .AddScoped(typeof(typeof(ServiceObject))
100 | .BuildServiceProvider();
101 |
102 | using (var scope = serviceProvider.CreateScope())
103 | {
104 | var service = scope.ServiceProvider.GetServices(typeof(ServiceObject));
105 | service.ServiceObject.Three = "3";
106 | }
107 | ```
108 |
109 | ## Activator Utilities
110 |
111 | An instance of an object can be created by calling its constructor with any dependencies resolved through the service provider. Automatically instantiate a type with constructor arguments provided from an IServiceProvider without having to register the type with the DI Container.
112 |
113 | ```csharp
114 | var instance = (RootObject)ActivatorUtilities.CreateInstance(
115 | serviceProvider, typeof(RootObject), 1, "2"
116 | );
117 |
118 | Debug.WriteLine($"One: {instance.One}");
119 | Debug.WriteLine($"Two: {instance.Two}");
120 | Debug.WriteLine($"Three: {instance.ServiceObject.Three}");
121 | Debug.WriteLine($"Name: {instance.ServiceObject.GetType().Name}");
122 | ```
123 |
124 | ### Validate On Build
125 |
126 | A check is performed to ensure that all services registered with the container can actually be created. This can be particularly useful during development to fail fast and allow developers to fix the issue. Validate on build is configured false by default.
127 |
128 | ```csharp
129 | var serviceProvider = new ServiceCollection()
130 | .AddSingleton(typeof(IServiceObject), typeof(ServiceObject))
131 | .BuildServiceProvider(new ServiceProviderOptions() { ValidateOnBuild = true });
132 | ```
133 |
134 | ### Validate Scopes
135 |
136 | A check verifying that scoped services never gets resolved from root provider. Validate on build is configured false by default.
137 |
138 | ```csharp
139 | var serviceProvider = new ServiceCollection()
140 | .AddSingleton(typeof(IServiceObject), typeof(ServiceObject))
141 | .BuildServiceProvider(new ServiceProviderOptions() { ValidateScopes = true });
142 | ```
143 |
144 | ## Example Application Container
145 |
146 | ```csharp
147 | using System;
148 | using System.Device.Gpio;
149 | using System.Threading;
150 |
151 | using nanoFramework.Logging.Debug;
152 | using nanoFramework.DependencyInjection;
153 |
154 | using Microsoft.Extensions.Logging;
155 |
156 | nanoFramework.DiApplication
157 | {
158 | public class Program
159 | {
160 | public static void Main()
161 | {
162 | var services = ConfigureServices();
163 | var application = (Application)services.GetRequiredService(typeof(Application));
164 |
165 | application.Run();
166 | }
167 |
168 | private static ServiceProvider ConfigureServices()
169 | {
170 | return new ServiceCollection()
171 | .AddSingleton(typeof(Application))
172 | .AddSingleton(typeof(IHardwareService), typeof(HardwareService))
173 | .AddSingleton(typeof(ILoggerFactory), typeof(DebugLoggerFactory))
174 | .BuildServiceProvider();
175 | }
176 | }
177 |
178 | internal class Application
179 | {
180 | private readonly ILogger _logger;
181 | private readonly IHardwareService _hardware;
182 | private readonly IServiceProvider _provider;
183 |
184 | public Application(
185 | IServiceProvider provider,
186 | IHardwareService hardware,
187 | ILoggerFactory loggerFactory)
188 | {
189 | _provider = provider;
190 | _hardware = hardware;
191 | _logger = loggerFactory.CreateLogger(nameof(Application));
192 |
193 | _logger.LogInformation("Initializing application...");
194 | }
195 |
196 | public void Run()
197 | {
198 | var ledPin = 23; // Set pin number to blink 15=ESP32; 23=STM32
199 |
200 | _logger.LogInformation($"Started blinking led on pin {ledPin}.");
201 | _hardware.StartBlinking(ledPin);
202 | }
203 | }
204 |
205 | internal interface IHardwareService
206 | {
207 | public void StartBlinking(int ledPin) { }
208 | }
209 |
210 | internal class HardwareService : IHardwareService, IDisposable
211 | {
212 | private Thread _thread;
213 | private readonly ILogger _logger;
214 | private readonly GpioController _gpioController;
215 |
216 | public HardwareService()
217 | {
218 | _gpioController = new GpioController();
219 |
220 | var loggerFactory = new DebugLoggerFactory();
221 | _logger = loggerFactory.CreateLogger(nameof(HardwareService));
222 | }
223 |
224 | public HardwareService(ILoggerFactory loggerFactory)
225 | {
226 | _gpioController = new GpioController();
227 | _logger = loggerFactory.CreateLogger(nameof(HardwareService));
228 | }
229 |
230 | public void StartBlinking(int ledPin)
231 | {
232 | GpioPin led = _gpioController.OpenPin(ledPin, PinMode.Output);
233 | led.Write(PinValue.Low);
234 |
235 | _thread = new Thread(() =>
236 | {
237 | while (true)
238 | {
239 | Thread.Sleep(2000);
240 |
241 | led.Write(PinValue.High);
242 | _logger.LogInformation("Led status: on");
243 |
244 | Thread.Sleep(2000);
245 |
246 | led.Write(PinValue.Low);
247 | _logger.LogInformation("Led status: off");
248 | }
249 | });
250 |
251 | _thread.Start();
252 | }
253 |
254 | public void Dispose()
255 | {
256 | _gpioController.Dispose();
257 | }
258 | }
259 | }
260 | ```
261 |
262 | ## Feedback and documentation
263 |
264 | For documentation, providing feedback, issues and finding out how to contribute please refer to the [Home repo](https://github.com/nanoframework/Home).
265 |
266 | Join our Discord community [here](https://discord.gg/gCyBu8T).
267 |
268 | ## Credits
269 |
270 | The list of contributors to this project can be found at [CONTRIBUTORS](https://github.com/nanoframework/Home/blob/main/CONTRIBUTORS.md).
271 |
272 | ## License
273 |
274 | The **nanoFramework** Class Libraries are licensed under the [MIT license](LICENSE.md).
275 |
276 | ## Code of Conduct
277 |
278 | This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behaviour in our community.
279 | For more information see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
280 |
281 | ## .NET Foundation
282 |
283 | This project is supported by the [.NET Foundation](https://dotnetfoundation.org).
284 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceCollectionServiceExtensions.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 |
8 | namespace Microsoft.Extensions.DependencyInjection
9 | {
10 | ///
11 | /// Extension methods for adding services to an .
12 | ///
13 | public static class ServiceCollectionServiceExtensions
14 | {
15 | ///
16 | /// Adds a transient service of the type specified in with an
17 | /// implementation of the type specified in to the
18 | /// specified .
19 | ///
20 | /// The to add the service to.
21 | /// The type of the service to register.
22 | /// The implementation type of the service.
23 | /// A reference to this instance after the operation has completed.
24 | ///
25 | public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType, Type implementationType)
26 | {
27 | ArgumentNullException.ThrowIfNull(services);
28 | ArgumentNullException.ThrowIfNull(serviceType);
29 | ArgumentNullException.ThrowIfNull(implementationType);
30 |
31 | return Add(services, serviceType, implementationType, ServiceLifetime.Transient);
32 | }
33 |
34 | ///
35 | /// Adds a transient service of the type specified in with a
36 | /// factory specified in to the
37 | /// specified .
38 | ///
39 | /// The to add the service to.
40 | /// The type of the service to register.
41 | /// The factory that creates the service.
42 | /// A reference to this instance after the operation has completed.
43 | ///
44 | public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType, ImplementationFactoryDelegate implementationFactory)
45 | {
46 | ArgumentNullException.ThrowIfNull(services);
47 | ArgumentNullException.ThrowIfNull(serviceType);
48 | ArgumentNullException.ThrowIfNull(implementationFactory);
49 |
50 | return Add(services, serviceType, implementationFactory, ServiceLifetime.Transient);
51 | }
52 |
53 | ///
54 | /// Adds a transient service of the type specified in to the
55 | /// specified .
56 | ///
57 | /// The to add the service to.
58 | /// The type of the service to register and the implementation to use.
59 | /// A reference to this instance after the operation has completed.
60 | ///
61 | public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType)
62 | {
63 | ArgumentNullException.ThrowIfNull(services);
64 | ArgumentNullException.ThrowIfNull(serviceType);
65 |
66 | return services.AddTransient(serviceType, serviceType);
67 | }
68 |
69 | ///
70 | /// Adds a scoped service of the type specified in with an
71 | /// implementation of the type specified in to the
72 | /// specified .
73 | ///
74 | /// The to add the service to.
75 | /// The type of the service to register.
76 | /// The implementation type of the service.
77 | /// A reference to this instance after the operation has completed.
78 | ///
79 | public static IServiceCollection AddScoped(this IServiceCollection services, Type serviceType, Type implementationType)
80 | {
81 | ArgumentNullException.ThrowIfNull(services);
82 | ArgumentNullException.ThrowIfNull(serviceType);
83 | ArgumentNullException.ThrowIfNull(implementationType);
84 |
85 | return Add(services, serviceType, implementationType, ServiceLifetime.Scoped);
86 | }
87 |
88 | ///
89 | /// Adds a scoped service of the type specified in with a
90 | /// factory specified in to the
91 | /// specified .
92 | ///
93 | /// The to add the service to.
94 | /// The type of the service to register.
95 | /// The factory that creates the service.
96 | /// A reference to this instance after the operation has completed.
97 | ///
98 | public static IServiceCollection AddScoped(this IServiceCollection services, Type serviceType, ImplementationFactoryDelegate implementationFactory)
99 | {
100 | ArgumentNullException.ThrowIfNull(services);
101 | ArgumentNullException.ThrowIfNull(serviceType);
102 | ArgumentNullException.ThrowIfNull(implementationFactory);
103 |
104 | return Add(services, serviceType, implementationFactory, ServiceLifetime.Scoped);
105 | }
106 |
107 | ///
108 | /// Adds a scoped service of the type specified in to the
109 | /// specified .
110 | ///
111 | /// The to add the service to.
112 | /// The type of the service to register and the implementation to use.
113 | /// A reference to this instance after the operation has completed.
114 | ///
115 | public static IServiceCollection AddScoped(this IServiceCollection services, Type serviceType)
116 | {
117 | ArgumentNullException.ThrowIfNull(services);
118 | ArgumentNullException.ThrowIfNull(serviceType);
119 |
120 | return services.AddScoped(serviceType, serviceType);
121 | }
122 |
123 | ///
124 | /// Adds a singleton service of the type specified in with an
125 | /// implementation of the type specified in to the
126 | /// specified .
127 | ///
128 | /// The to add the service to.
129 | /// The type of the service to register.
130 | /// The implementation type of the service.
131 | /// A reference to this instance after the operation has completed.
132 | ///
133 | public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, Type implementationType)
134 | {
135 | ArgumentNullException.ThrowIfNull(services);
136 | ArgumentNullException.ThrowIfNull(serviceType);
137 | ArgumentNullException.ThrowIfNull(implementationType);
138 |
139 | return Add(services, serviceType, implementationType, ServiceLifetime.Singleton);
140 | }
141 |
142 | ///
143 | /// Adds a singleton service of the type specified in with a
144 | /// factory specified in to the
145 | /// specified .
146 | ///
147 | /// The to add the service to.
148 | /// The type of the service to register.
149 | /// The factory that creates the service.
150 | /// A reference to this instance after the operation has completed.
151 | ///
152 | public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, ImplementationFactoryDelegate implementationFactory)
153 | {
154 | ArgumentNullException.ThrowIfNull(services);
155 | ArgumentNullException.ThrowIfNull(serviceType);
156 | ArgumentNullException.ThrowIfNull(implementationFactory);
157 |
158 | return Add(services, serviceType, implementationFactory, ServiceLifetime.Singleton);
159 | }
160 |
161 | ///
162 | /// Adds a singleton service of the type specified in to the
163 | /// specified .
164 | ///
165 | /// The to add the service to.
166 | /// The type of the service to register and the implementation to use.
167 | /// A reference to this instance after the operation has completed.
168 | ///
169 | public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType)
170 | {
171 | ArgumentNullException.ThrowIfNull(services);
172 | ArgumentNullException.ThrowIfNull(serviceType);
173 |
174 | return services.AddSingleton(serviceType, serviceType);
175 | }
176 |
177 | ///
178 | /// Adds a singleton service of the type specified in with an
179 | /// instance specified in to the
180 | /// specified .
181 | ///
182 | /// The to add the service to.
183 | /// The type of the service to register.
184 | /// The instance of the service.
185 | /// A reference to this instance after the operation has completed.
186 | ///
187 | public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, object implementationInstance)
188 | {
189 | ArgumentNullException.ThrowIfNull(services);
190 | ArgumentNullException.ThrowIfNull(serviceType);
191 | ArgumentNullException.ThrowIfNull(implementationInstance);
192 |
193 | var serviceDescriptor = new ServiceDescriptor(serviceType, implementationInstance);
194 | services.Add(serviceDescriptor);
195 | return services;
196 | }
197 |
198 | private static IServiceCollection Add(IServiceCollection collection, Type serviceType, Type implementationType, ServiceLifetime lifetime)
199 | {
200 | var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime);
201 | collection.Add(descriptor);
202 | return collection;
203 | }
204 |
205 | private static IServiceCollection Add(IServiceCollection collection, Type serviceType, ImplementationFactoryDelegate implementationFactory, ServiceLifetime lifetime)
206 | {
207 | var descriptor = new ServiceDescriptor(serviceType, implementationFactory, lifetime);
208 | collection.Add(descriptor);
209 | return collection;
210 | }
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceDescriptor.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 | using System.Diagnostics;
8 |
9 | namespace Microsoft.Extensions.DependencyInjection
10 | {
11 | ///
12 | /// Service Factory method delegate
13 | ///
14 | public delegate object ImplementationFactoryDelegate(IServiceProvider serviceProvider);
15 |
16 | ///
17 | /// Describes a service with its service type, implementation, and lifetime.
18 | ///
19 | [DebuggerDisplay("Lifetime = {Lifetime}, ServiceType = {ServiceType}, ImplementationType = {ImplementationType}")]
20 | public class ServiceDescriptor
21 | {
22 | ///
23 | /// Initializes a new instance of with the specified .
24 | ///
25 | /// The of the service.
26 | /// The implementing the service.
27 | /// The of the service.
28 | /// or can't be null
29 | /// Implementation type cannot be an abstract or interface class.
30 | public ServiceDescriptor(Type serviceType, Type implementationType, ServiceLifetime lifetime): this(serviceType, lifetime)
31 | {
32 | ArgumentNullException.ThrowIfNull(serviceType);
33 | ArgumentNullException.ThrowIfNull(implementationType);
34 |
35 | if (implementationType.IsAbstract || implementationType.IsInterface)
36 | {
37 | throw new ArgumentException();
38 | }
39 |
40 | ImplementationType = implementationType;
41 | }
42 |
43 | ///
44 | /// Initializes a new instance of with the specified
45 | /// as a .
46 | ///
47 | /// The of the service.
48 | /// The instance implementing the service.
49 | /// or can't be
50 | public ServiceDescriptor(Type serviceType, object instance): this(serviceType, ServiceLifetime.Singleton)
51 | {
52 | ArgumentNullException.ThrowIfNull(serviceType);
53 | ArgumentNullException.ThrowIfNull(instance);
54 |
55 | ImplementationInstance = instance;
56 | ImplementationType = instance.GetType();
57 | }
58 |
59 | ///
60 | /// Initializes a new instance of with the specified .
61 | ///
62 | /// The of the service.
63 | /// A factory used for creating service instances.
64 | /// The of the service.
65 | /// can't be null
66 | /// can't be null
67 | /// Implementation type cannot be an abstract or interface class.
68 | public ServiceDescriptor(Type serviceType, ImplementationFactoryDelegate implementationFactory, ServiceLifetime lifetime): this(serviceType, lifetime)
69 | {
70 | ArgumentNullException.ThrowIfNull(serviceType);
71 | ArgumentNullException.ThrowIfNull(implementationFactory);
72 |
73 | ImplementationFactory = implementationFactory;
74 | }
75 |
76 | private ServiceDescriptor(Type serviceType, ServiceLifetime lifetime)
77 | {
78 | ServiceType = serviceType;
79 | Lifetime = lifetime;
80 | }
81 |
82 | ///
83 | /// The of the service.
84 | ///
85 | public ServiceLifetime Lifetime { get; }
86 |
87 | ///
88 | /// The of the service.
89 | ///
90 | public Type ServiceType { get; }
91 |
92 | ///
93 | /// The implementing the service.
94 | ///
95 | public Type ImplementationType { get; }
96 |
97 | ///
98 | /// The instance of the implementation.
99 | ///
100 | public object ImplementationInstance { get; set; }
101 |
102 | ///
103 | /// Gets the factory used for creating service instances.
104 | ///
105 | public ImplementationFactoryDelegate ImplementationFactory { get; set; }
106 |
107 | ///
108 | /// Returns a string that represents the current object.
109 | ///
110 | public override string ToString()
111 | {
112 | string lifetime = $"{nameof(ServiceType)}: {ServiceType} {nameof(Lifetime)}: {Lifetime} ";
113 |
114 | if (ImplementationType != null)
115 | {
116 | return lifetime + $"{nameof(ImplementationType)}: {ImplementationType}";
117 | }
118 |
119 | return lifetime + $"{nameof(ImplementationInstance)}: {ImplementationInstance}";
120 | }
121 |
122 | ///
123 | /// Returns the implementing the instance.
124 | ///
125 | public Type GetImplementationType()
126 | {
127 | if (ImplementationType != null)
128 | {
129 | return ImplementationType;
130 | }
131 | else if (ImplementationInstance != null)
132 | {
133 | return ImplementationInstance.GetType();
134 | }
135 | // TODO: This case is not currently handled which means we cannot currently support factories in the TryAdd methods.
136 | // A possible solution would be to require the implementation type to be supplied with the factory.
137 | /*
138 | else if (ImplementationFactory != null)
139 | {
140 | Type[]? typeArguments = ImplementationFactory.GetType().GenericTypeArguments;
141 |
142 | Debug.Assert(typeArguments.Length == 2);
143 |
144 | return typeArguments[1];
145 | }
146 | */
147 |
148 | Debug.Assert(false, "ImplementationType and ImplementationInstance must be non null");
149 |
150 | return null;
151 | }
152 |
153 | ///
154 | /// Creates an instance of with the specified
155 | /// , ,
156 | /// and .
157 | ///
158 | /// The type of the service.
159 | /// The type of the implementation.
160 | /// The lifetime of the service.
161 | /// A new instance of .
162 | public static ServiceDescriptor Describe(Type serviceType, Type implementationType, ServiceLifetime lifetime)
163 | {
164 | ArgumentNullException.ThrowIfNull(serviceType);
165 | ArgumentNullException.ThrowIfNull(implementationType);
166 |
167 | return new ServiceDescriptor(serviceType, implementationType, lifetime);
168 | }
169 |
170 | ///
171 | /// Creates an instance of with the specified
172 | /// , ,
173 | /// and .
174 | ///
175 | /// The type of the service.
176 | /// A factory to create new instances of the service implementation.
177 | /// The lifetime of the service.
178 | /// A new instance of .
179 | public static ServiceDescriptor Describe(Type serviceType, ImplementationFactoryDelegate implementationFactory, ServiceLifetime lifetime)
180 | {
181 | ArgumentNullException.ThrowIfNull(serviceType);
182 | ArgumentNullException.ThrowIfNull(implementationFactory);
183 |
184 | return new ServiceDescriptor(serviceType, implementationFactory, lifetime);
185 | }
186 |
187 | ///
188 | /// Creates an instance of with the specified
189 | /// and
190 | /// and the lifetime.
191 | ///
192 | /// The type of the service.
193 | /// The type of the implementation.
194 | /// A new instance of .
195 | public static ServiceDescriptor Scoped(Type service, Type implementationType)
196 | {
197 | return Describe(service, implementationType, ServiceLifetime.Scoped);
198 | }
199 |
200 | ///
201 | /// Creates an instance of with the specified
202 | /// and
203 | /// and the lifetime.
204 | ///
205 | /// The type of the service.
206 | /// A factory to create new instances of the service implementation.
207 | /// A new instance of .
208 | public static ServiceDescriptor Scoped(Type service, ImplementationFactoryDelegate implementationFactory)
209 | {
210 | return Describe(service, implementationFactory, ServiceLifetime.Scoped);
211 | }
212 |
213 | ///
214 | /// Creates an instance of with the specified
215 | /// and
216 | /// and the lifetime.
217 | ///
218 | /// The type of the service.
219 | /// The type of the implementation.
220 | /// A new instance of .
221 | public static ServiceDescriptor Singleton(Type service, Type implementationType)
222 | {
223 | return Describe(service, implementationType, ServiceLifetime.Singleton);
224 | }
225 |
226 | ///
227 | /// Creates an instance of with the specified
228 | /// and
229 | /// and the lifetime.
230 | ///
231 | /// The type of the service.
232 | /// A factory to create new instances of the service implementation.
233 | /// A new instance of .
234 | public static ServiceDescriptor Singleton(Type service, ImplementationFactoryDelegate implementationFactory)
235 | {
236 | return Describe(service, implementationFactory, ServiceLifetime.Singleton);
237 | }
238 |
239 | ///
240 | /// Creates an instance of with the specified
241 | /// and
242 | /// and the lifetime.
243 | ///
244 | /// The type of the service.
245 | /// The type of the implementation.
246 | /// A new instance of .
247 | public static ServiceDescriptor Transient(Type service, Type implementationType)
248 | {
249 | return Describe(service, implementationType, ServiceLifetime.Transient);
250 | }
251 |
252 | ///
253 | /// Creates an instance of with the specified
254 | /// and
255 | /// and the lifetime.
256 | ///
257 | /// The type of the service.
258 | /// A factory to create new instances of the service implementation.
259 | /// A new instance of .
260 | public static ServiceDescriptor Transient(Type service, ImplementationFactoryDelegate implementationFactory)
261 | {
262 | return Describe(service, implementationFactory, ServiceLifetime.Transient);
263 | }
264 | }
265 | }
266 |
--------------------------------------------------------------------------------
/nanoFramework.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceProviderEngine.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) .NET Foundation and Contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | using System;
7 | using System.Reflection;
8 | using System.Collections;
9 |
10 | namespace Microsoft.Extensions.DependencyInjection
11 | {
12 | ///
13 | /// Defines an engine for managing services that provides custom support to other objects.
14 | ///
15 | internal sealed class ServiceProviderEngine
16 | {
17 | internal static ServiceProviderEngine Instance { get; } = new ServiceProviderEngine();
18 |
19 | private ServiceProviderEngine() { }
20 |
21 | ///
22 | /// A collection of implemented services.
23 | ///
24 | internal IServiceCollection Services { get; set; }
25 |
26 | ///
27 | /// ServiceProvider Options instance
28 | ///
29 | internal ServiceProviderOptions Options { get; set; }
30 |
31 | ///
32 | /// Validate service by attempting to activate all dependent services.
33 | ///
34 | internal void ValidateService(ServiceDescriptor descriptor)
35 | {
36 | GetService(descriptor.GetImplementationType());
37 | }
38 |
39 | ///
40 | /// Dispose of all service descriptors in services.
41 | ///
42 | internal void DisposeServices()
43 | {
44 | for (int index = Services.Count - 1; index >= 0; index--)
45 | {
46 | if (Services[index].ImplementationInstance is IDisposable disposable)
47 | {
48 | disposable.Dispose();
49 | }
50 | }
51 | }
52 |
53 | ///
54 | /// Gets the last added service object of the specified type.
55 | ///
56 | /// An object that specifies the type of service object to get.
57 | /// Services collection from current scope.
58 | internal object GetService(Type serviceType, IServiceCollection scopeServices = null)
59 | {
60 | var services = GetServiceObjects(serviceType, scopeServices);
61 |
62 | if (services.Length == 0)
63 | {
64 | return null;
65 | }
66 |
67 | // returns the last added service of this type
68 | return services[services.Length - 1];
69 | }
70 |
71 | ///
72 | /// Gets the service objects of the specified type.
73 | ///
74 | /// An object that specifies the type of service object to get.
75 | /// Services collection from current scope.
76 | /// can't be .
77 | /// can't be empty.
78 | internal object[] GetService(Type[] serviceType, IServiceCollection scopeServices = null)
79 | {
80 | if (serviceType == null)
81 | {
82 | throw new ArgumentNullException();
83 | }
84 |
85 | if (serviceType.Length == 0)
86 | {
87 | throw new ArgumentException();
88 | }
89 |
90 | // optimized for single item service type
91 | if (serviceType.Length == 1)
92 | {
93 | var services = GetServiceObjects(serviceType[0], scopeServices);
94 |
95 | if (services.Length > 0)
96 | {
97 | return services;
98 | }
99 |
100 | return new object[0];
101 | }
102 |
103 | // multiple service type items
104 | object[] array = new object[0];
105 |
106 | foreach (Type type in serviceType)
107 | {
108 | var services = GetServiceObjects(type, scopeServices);
109 |
110 | if (services.Length > 0)
111 | {
112 | var newArray = new object[array.Length + services.Length];
113 |
114 | Array.Copy(array, newArray, array.Length);
115 | Array.Copy(services, 0, newArray, array.Length, services.Length);
116 |
117 | array = newArray;
118 | }
119 | }
120 |
121 | return array.Length != 0 ? array : new object[0];
122 | }
123 |
124 | ///
125 | /// Gets the service objects of the specified type.
126 | ///
127 | /// An object that specifies the type of service object to get.
128 | /// Services collection from current scope.
129 | private object[] GetServiceObjects(Type serviceType, IServiceCollection scopeServices)
130 | {
131 | ArrayList services = new ArrayList();
132 |
133 | if (scopeServices != null)
134 | {
135 | foreach (ServiceDescriptor descriptor in scopeServices)
136 | {
137 | if (descriptor.ServiceType != serviceType) continue;
138 |
139 | descriptor.ImplementationInstance ??=
140 | descriptor.ImplementationFactory?.Invoke((IServiceProvider)GetService(typeof(IServiceProvider)))
141 | ?? Resolve(descriptor.ImplementationType);
142 | services.Add(descriptor.ImplementationInstance);
143 | }
144 | }
145 |
146 | foreach (ServiceDescriptor descriptor in Services)
147 | {
148 | if (descriptor.ServiceType != serviceType) continue;
149 |
150 | switch (descriptor.Lifetime)
151 | {
152 | case ServiceLifetime.Singleton:
153 | descriptor.ImplementationInstance ??=
154 | descriptor.ImplementationFactory?.Invoke((IServiceProvider)GetService(typeof(IServiceProvider)))
155 | ?? Resolve(descriptor.ImplementationType);
156 | services.Add(descriptor.ImplementationInstance);
157 | break;
158 |
159 | case ServiceLifetime.Transient:
160 | services.Add(descriptor.ImplementationFactory?.Invoke((IServiceProvider)GetService(typeof(IServiceProvider)))
161 | ?? Resolve(descriptor.ImplementationType));
162 | break;
163 |
164 | case ServiceLifetime.Scoped:
165 | if (scopeServices == null && Options.ValidateScopes)
166 | {
167 | throw new InvalidOperationException();
168 | }
169 | break;
170 | }
171 | }
172 |
173 | return (object[])services.ToArray(typeof(object));
174 | }
175 |
176 | ///
177 | /// Resolve and activates the specified implementation type.
178 | ///
179 | /// An object that specifies the implementation type of service object to get.
180 | /// A suitable constructor for type could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.
181 | /// Unable to resolve service for type while attempting to activate.
182 | private object Resolve(Type implementationType)
183 | {
184 | object instance;
185 |
186 | ParameterInfo[] constructorParameters = GetParameters(implementationType);
187 |
188 | if (constructorParameters == null)
189 | {
190 | throw new InvalidOperationException(
191 | $"Constructor for '{implementationType}' could not be located.");
192 | }
193 |
194 | if (constructorParameters.Length == 0)
195 | {
196 | instance = Activator.CreateInstance(implementationType);
197 | }
198 | else
199 | {
200 | Type[] types = new Type[constructorParameters.Length];
201 | object[] parameters = new object[constructorParameters.Length];
202 |
203 | for (int index = 0; index < constructorParameters.Length; index++)
204 | {
205 | var parameterType = constructorParameters[index].ParameterType;
206 |
207 | if (parameterType.IsResolvable())
208 | {
209 | types[index] = parameterType;
210 | parameters[index] = GetResolvableDefault(parameterType);
211 | }
212 | else
213 | {
214 | var service = parameterType.IsArray ?
215 | GetServiceObjects(parameterType.GetElementType(), null) :
216 | GetService(parameterType);
217 |
218 | if (service == null)
219 | {
220 | throw new InvalidOperationException(
221 | $"Unable to resolve service for '{parameterType}'.");
222 | }
223 |
224 | types[index] = parameterType;
225 | parameters[index] = service;
226 | }
227 | }
228 |
229 | instance = Activator.CreateInstance(implementationType, types, parameters);
230 | }
231 |
232 | return instance;
233 | }
234 |
235 | ///
236 | /// Gets the parameters from the constructor with the most parameters that can be resolved.
237 | ///
238 | /// An object that specifies the implementation type of service object to get.
239 | /// Multiple constructors accepting all given argument types have been found in type . There should only be one applicable constructor.
240 | private ParameterInfo[] GetParameters(Type implementationType)
241 | {
242 | int bestLength = -1;
243 |
244 | ParameterInfo[] bestParameters = null;
245 | ConstructorInfo[] constructors = implementationType.GetConstructors();
246 |
247 | // step 1: check for multiple constructors with same number of arguments
248 | for (int i = 0; i < constructors.Length; i++)
249 | {
250 | for (int j = i; j < constructors.Length - 1; j++)
251 | {
252 | if (constructors[j].GetParameters().Length == constructors[j + 1].GetParameters().Length)
253 | {
254 | throw new InvalidOperationException(
255 | $"Multiple constructors found in '{implementationType}'.");
256 | }
257 | }
258 | }
259 |
260 | // step 2: get the constructor with the most resolvable parameters
261 | foreach (ConstructorInfo constructor in constructors)
262 | {
263 | ParameterInfo[] parameters = constructor.GetParameters();
264 |
265 | int length = parameters.Length;
266 |
267 | foreach (ParameterInfo parameter in parameters)
268 | {
269 | Type type = parameter.ParameterType;
270 |
271 | if (type.IsResolvable())
272 | {
273 | // check for simple binding first
274 | }
275 | else
276 | {
277 | if (!IsService(type))
278 | {
279 | // binding could not be resolved ignore constructor
280 | length = -1;
281 | break;
282 | }
283 |
284 | }
285 | }
286 |
287 | if (bestLength < length)
288 | {
289 | bestLength = length;
290 | bestParameters = parameters;
291 | }
292 | }
293 |
294 | return bestParameters;
295 | }
296 |
297 | ///
298 | /// Get primitive default type.
299 | ///
300 | private static object GetResolvableDefault(Type type)
301 | {
302 | // This list dosn't match the IsResolvable() because
303 | // we only check for items we know are not null by default
304 | if (type == typeof(object)) return default;
305 | if (type == typeof(int)) return default(int);
306 | if (type == typeof(uint)) return default(uint);
307 | if (type == typeof(bool)) return default(bool);
308 | if (type == typeof(char)) return default(char);
309 | if (type == typeof(byte)) return default(byte);
310 | if (type == typeof(sbyte)) return default(sbyte);
311 | if (type == typeof(short)) return default(short);
312 | if (type == typeof(ushort)) return default(ushort);
313 | if (type == typeof(long)) return default(long);
314 | if (type == typeof(ulong)) return default(ulong);
315 | if (type == typeof(double)) return default(double);
316 | if (type == typeof(float)) return default(float);
317 | if (type == typeof(Guid)) return default(Guid);
318 | if (type == typeof(DateTime)) return default(DateTime);
319 | if (type == typeof(TimeSpan)) return default(TimeSpan);
320 |
321 | return null;
322 | }
323 |
324 | ///
325 | /// Determines if the specified service type is available from the .
326 | ///
327 | /// An object that specifies the type of service object to test.
328 | /// true if the specified service is a available, false if it is not.
329 | internal bool IsService(Type serviceType)
330 | {
331 | if (serviceType.IsArray)
332 | {
333 | serviceType = serviceType.GetElementType();
334 | }
335 |
336 | foreach (ServiceDescriptor descriptor in Services)
337 | {
338 | if (descriptor.ServiceType == serviceType)
339 | {
340 | return true;
341 | }
342 | }
343 |
344 | return false;
345 | }
346 | }
347 | }
348 |
--------------------------------------------------------------------------------