From b3a48264c2fb6d5b1a88a1e051bcf0a03753ff07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Jun 2021 05:01:03 +0000 Subject: [PATCH 01/17] Bump NUnit3TestAdapter in /tests/StackInjector.TEST.BlackBox Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 3.17.0 to 4.0.0. - [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases) - [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V3.17...V4.0.0) --- updated-dependencies: - dependency-name: NUnit3TestAdapter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .../StackInjector.TEST.BlackBox.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/StackInjector.TEST.BlackBox/StackInjector.TEST.BlackBox.csproj b/tests/StackInjector.TEST.BlackBox/StackInjector.TEST.BlackBox.csproj index 2567816..7638ff7 100644 --- a/tests/StackInjector.TEST.BlackBox/StackInjector.TEST.BlackBox.csproj +++ b/tests/StackInjector.TEST.BlackBox/StackInjector.TEST.BlackBox.csproj @@ -20,7 +20,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From bdf70684f86aec2e95526f4db7f89a5b3eb59f70 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Fri, 18 Jun 2021 19:26:47 +0200 Subject: [PATCH 02/17] Added VersioningOptions - added VOp to StackWrapperSettings - moved InjectionOptions.VersioningMethod to VersioningOptions - updated tests --- .../InjectionCore/InjectionCore.reflection.cs | 8 +- .../InjectionCore/InjectionCore.versioning.cs | 23 +++-- StackInjector/Settings/InjectionOptions.cs | 23 +---- StackInjector/Settings/MaskOptions.cs | 4 +- .../Settings/StackWrapperSettings.cs | 22 ++++- StackInjector/Settings/VersioningOptions.cs | 87 +++++++++++++++++++ tests/StackInjector.TEST.BlackBox/Injector.cs | 38 ++++++-- 7 files changed, 162 insertions(+), 43 deletions(-) create mode 100644 StackInjector/Settings/VersioningOptions.cs diff --git a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs index 60a6eb5..caa655a 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Data; using System.Linq; using StackInjector.Attributes; using StackInjector.Exceptions; @@ -16,7 +17,7 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr { IEnumerable versions = this.instances.TypesAssignableFrom(type); - // is there already an implementation for the interface? + // has an implementation for the interface already been found? if ( versions.Any() ) { return versions.First(); @@ -26,6 +27,7 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr versions = this.Version(type, servedAttribute); if ( versions.Any() ) { + //todo check for multiple valid versions var t = versions.First(); MaskPass(t); return t; @@ -46,9 +48,9 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr void MaskPass ( Type type ) { - if ( this.settings.Mask.IsMasked(type) ) + if ( this.settings.Mask.IsMasked(type) ) //todo create custom exception throw new InvalidOperationException($"Type {type.Name} is { (this.settings.Mask._isWhiteList ? "not whitelisted" : "blacklisted")}"); - //todo create custom exception + } diff --git a/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs index 283cfc3..d3b94a3 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs @@ -15,16 +15,23 @@ private IEnumerable Version ( Type targetType, ServedAttribute servedAttri var targetVersion = servedAttribute?.TargetVersion ?? 0.0; var method = - (this.settings.Injection._overrideTargetingMethod || servedAttribute is null || !(servedAttribute._targetingDefined)) - ? this.settings.Injection._targetingMethod + (this.settings.Versioning._overrideTargetingMethod || servedAttribute is null || !(servedAttribute._targetingDefined)) + ? this.settings.Versioning._targetingMethod : servedAttribute.TargetingMethod; - - ////var candidateTypes = this.instances.TypesAssignableFrom(targetType); - var candidateTypes = targetType - .Assembly - .GetTypes() - .Where( t => t.IsClass && !t.IsAbstract && targetType.IsAssignableFrom(t)); + IEnumerable candidateTypes = + (this.settings.Versioning.AssemblyLookUpOrder.Any()) + ? + this.settings.Versioning + .AssemblyLookUpOrder + .SelectMany( a => a.DefinedTypes ) + .Where( t => t.IsClass && !t.IsAbstract + && targetType.IsAssignableFrom(t) && !this.settings.Mask.IsMasked(t) ) + : + targetType + .Assembly + .DefinedTypes + .Where( t => t.IsClass && !t.IsAbstract && targetType.IsAssignableFrom(t) ); return method switch diff --git a/StackInjector/Settings/InjectionOptions.cs b/StackInjector/Settings/InjectionOptions.cs index 7279921..b9cc797 100644 --- a/StackInjector/Settings/InjectionOptions.cs +++ b/StackInjector/Settings/InjectionOptions.cs @@ -5,12 +5,10 @@ namespace StackInjector.Settings { /// - /// Options for the injection process. + /// Options for the injection process, regarding HOW the inejction should be performed /// public sealed class InjectionOptions : IOptions { - internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; - internal bool _overrideTargetingMethod; internal ServingMethods _servingMethod = StackWrapperSettings.ServeAllStrict; internal bool _overrideServingMethod; @@ -42,10 +40,7 @@ public object Clone () /// /// The default injection. Settings are valorized as following: /// - /// - /// - /// , false - /// + /// /// /// , false /// @@ -82,20 +77,6 @@ public InjectionOptions TrackInstantiationDiff ( bool track = true, bool callDis return this; } - - /// - /// Overrides default targetting method - /// - /// the new default targetting method - /// if true, versioning methods for [Served] fields and properties are overriden - /// the modified settings - public InjectionOptions VersioningMethod ( ServedVersionTargetingMethod targetMethod, bool @override = false ) - { - this._targetingMethod = targetMethod; - this._overrideTargetingMethod = @override; - return this; - } - /// /// Overrides default serving method /// diff --git a/StackInjector/Settings/MaskOptions.cs b/StackInjector/Settings/MaskOptions.cs index d13f9e5..0be07d3 100644 --- a/StackInjector/Settings/MaskOptions.cs +++ b/StackInjector/Settings/MaskOptions.cs @@ -50,8 +50,8 @@ public bool IsMasked ( Type type ) { if ( _isDisabled ) return false; - else - return this._isWhiteList ^ this.Contains(type); //.XOR + + return this._isWhiteList ^ this.Contains(type); //.XOR } diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 25c7b79..3836813 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -18,6 +18,11 @@ public sealed partial class StackWrapperSettings /// public InjectionOptions Injection { get; private set; } + /// + /// manages versioning options. + /// + public VersioningOptions Versioning { get; private set; } + /// /// manages runtime options /// @@ -25,6 +30,7 @@ public sealed partial class StackWrapperSettings + private StackWrapperSettings () { } @@ -38,7 +44,8 @@ public StackWrapperSettings Clone () return With( (InjectionOptions)this.Injection.Clone(), (RuntimeOptions)this.Runtime.Clone(), - (MaskOptions)this.Mask.Clone() + (MaskOptions)this.Mask.Clone(), + (VersioningOptions)this.Versioning.Clone() ); } @@ -48,6 +55,7 @@ public StackWrapperSettings Clone () /// , /// , /// + /// /// public static StackWrapperSettings Default => With(); @@ -58,14 +66,18 @@ public StackWrapperSettings Clone () /// the injection options /// the runtime options /// mask options + /// versioning options /// - public static StackWrapperSettings With ( InjectionOptions injection = null, RuntimeOptions runtime = null, MaskOptions mask = null ) + public static StackWrapperSettings With ( + InjectionOptions injection = null, RuntimeOptions runtime = null, + MaskOptions mask = null, VersioningOptions versioning = null ) { return new StackWrapperSettings() { Mask = mask ?? MaskOptions.Disabled, Injection = injection ?? InjectionOptions.Default, - Runtime = runtime ?? RuntimeOptions.Default + Runtime = runtime ?? RuntimeOptions.Default, + Versioning = versioning ?? VersioningOptions.Default }; } @@ -83,8 +95,10 @@ public static StackWrapperSettings With ( InjectionOptions injection = null, Run mask: null, runtime: + null, + versioning: null - ); + ); } diff --git a/StackInjector/Settings/VersioningOptions.cs b/StackInjector/Settings/VersioningOptions.cs new file mode 100644 index 0000000..c6d62c7 --- /dev/null +++ b/StackInjector/Settings/VersioningOptions.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reflection; +using System.Text; + +namespace StackInjector.Settings +{ + + /// + /// Used to determine how to find the correct type from an interface. + /// + public sealed class VersioningOptions : IOptions + { + + internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; + internal bool _overrideTargetingMethod; + + /// + /// A set of assemblies overriding where to look up types in, when not empty. + /// + public HashSet AssemblyLookUpOrder { get; private set; } = new HashSet(); + + + + internal VersioningOptions () { } + + + + /// + /// The default versioning options, valorized as following: + /// + /// + /// + /// , false + /// + /// + /// empty + /// + /// + /// + public static VersioningOptions Default => new VersioningOptions(); + + + /// + public object Clone () => this.MemberwiseClone(); + + IOptions IOptions.CreateDefault () => Default; + + + + #region configuration methods + + /// + /// Overrides default versioning method + /// + /// the new default targeting method + /// if true, versioning methods for [Served] fields and properties are overriden + /// the modified settings + public VersioningOptions VersioningMethod ( ServedVersionTargetingMethod targetMethod, bool @override = false ) + { + this._targetingMethod = targetMethod; + this._overrideTargetingMethod = @override; + return this; + } + + + /// + /// add a range of assemblies from which, in order, look for types when injecting interfaces, overriding any default option. + /// + /// + /// + public VersioningOptions AddAssembliesToLookup ( params Assembly[] assemblies ) + { + foreach ( var a in assemblies ) + { + this.AssemblyLookUpOrder.Add(a); + } + return this; + } + + + + #endregion + + } +} diff --git a/tests/StackInjector.TEST.BlackBox/Injector.cs b/tests/StackInjector.TEST.BlackBox/Injector.cs index 8794a50..ff52bb2 100644 --- a/tests/StackInjector.TEST.BlackBox/Injector.cs +++ b/tests/StackInjector.TEST.BlackBox/Injector.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using System.IO.Pipes; using System.Linq; -using NUnit; +using System.Reflection; using NUnit.Framework; using StackInjector.Attributes; using StackInjector.Core; @@ -130,7 +129,7 @@ public void AlwaysCreate () private class _ExternalAssemblyReference_Class {[Served] public readonly ExternalAssembly.Externalclass externalclass; } [Test] - public void ExternalAssembly_NoRegistration_FromClass () + public void ExternalAssembly_FromClass_NoVers () { Assert.DoesNotThrow(() => Injector.From<_ExternalAssemblyReference_Class>()); } @@ -140,13 +139,42 @@ public void ExternalAssembly_NoRegistration_FromClass () private class _ExternalAssemblyReference_Interface {[Served] public readonly ExternalAssembly.IExternalClass externalclass; } [Test] - public void ExternalAssembly_NoRegistration_FromInterface () + public void ExternalAssembly_FromInterface_NoVers () { Assert.DoesNotThrow(() => Injector.From<_ExternalAssemblyReference_Interface>()); } - //todo asas + + + [Service(Version = 2.0)] + private class _ExternalAssemblyReference_Local : ExternalAssembly.IExternalClass + { + public void SomeMethod () => throw new NotImplementedException(); + } + + [Test] + public void ExternalAssembly_LocalImplementation_NoVers_Throws () + { + var settings = StackWrapperSettings.With( + mask: MaskOptions.BlackList + ); + settings.Mask.Add(typeof(ExternalAssembly.Externalclass)); + Assert.Throws( () => Injector.From<_ExternalAssemblyReference_Interface>(settings) ); + } + + [Test] + public void ExternalAssembly_LocalImplementation_Vers () + { + var settings = StackWrapperSettings.With( + mask: MaskOptions.BlackList + ); + settings.Mask.Add(typeof(ExternalAssembly.Externalclass)); + settings.Versioning.AddAssembliesToLookup(Assembly.GetExecutingAssembly()); + + var wrapper = Injector.From<_ExternalAssemblyReference_Interface>(settings); + Assert.IsInstanceOf<_ExternalAssemblyReference_Local>(wrapper.Entry.externalclass); + } } } \ No newline at end of file From 41762b5f543cda2ac12f463a4e89ee632668263f Mon Sep 17 00:00:00 2001 From: Jacopo Date: Fri, 18 Jun 2021 19:30:26 +0200 Subject: [PATCH 03/17] Code cleanup --- .../InjectionCore/InjectionCore.reflection.cs | 1 - .../InjectionCore/InjectionCore.versioning.cs | 8 ++++---- StackInjector/Core/StackWrapperCore.cs | 8 +++++--- StackInjector/Settings/MaskOptions.cs | 2 +- StackInjector/Settings/StackWrapperSettings.cs | 4 ++-- StackInjector/Settings/VersioningOptions.cs | 17 ++++++++++------- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs index caa655a..05741b2 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Data; using System.Linq; using StackInjector.Attributes; using StackInjector.Exceptions; diff --git a/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs index d3b94a3..481c535 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs @@ -19,15 +19,15 @@ private IEnumerable Version ( Type targetType, ServedAttribute servedAttri ? this.settings.Versioning._targetingMethod : servedAttribute.TargetingMethod; - IEnumerable candidateTypes = - (this.settings.Versioning.AssemblyLookUpOrder.Any()) + IEnumerable candidateTypes = + (this.settings.Versioning.AssemblyLookUpOrder.Any()) ? this.settings.Versioning .AssemblyLookUpOrder .SelectMany( a => a.DefinedTypes ) - .Where( t => t.IsClass && !t.IsAbstract + .Where( t => t.IsClass && !t.IsAbstract && targetType.IsAssignableFrom(t) && !this.settings.Mask.IsMasked(t) ) - : + : targetType .Assembly .DefinedTypes diff --git a/StackInjector/Core/StackWrapperCore.cs b/StackInjector/Core/StackWrapperCore.cs index 2071ccd..9a96bdd 100644 --- a/StackInjector/Core/StackWrapperCore.cs +++ b/StackInjector/Core/StackWrapperCore.cs @@ -26,7 +26,7 @@ public StackWrapperCore ( InjectionCore core, Type toRegister ) if ( !this.Core.instances.AddType(toRegister) ) this.Core.instances[toRegister].Clear(); this.Core.instances[toRegister].AddFirst(this); - + } @@ -38,8 +38,10 @@ public IEnumerable GetServices () .Select(o => (T)o); } - public int CountServices () => this.Core.instances.total_count; - + public int CountServices () + { + return this.Core.instances.total_count; + } public IClonedCore CloneCore ( StackWrapperSettings settings = null ) { diff --git a/StackInjector/Settings/MaskOptions.cs b/StackInjector/Settings/MaskOptions.cs index 0be07d3..d0e330b 100644 --- a/StackInjector/Settings/MaskOptions.cs +++ b/StackInjector/Settings/MaskOptions.cs @@ -50,7 +50,7 @@ public bool IsMasked ( Type type ) { if ( _isDisabled ) return false; - + return this._isWhiteList ^ this.Contains(type); //.XOR } diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 3836813..912f6da 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -68,8 +68,8 @@ public StackWrapperSettings Clone () /// mask options /// versioning options /// - public static StackWrapperSettings With ( - InjectionOptions injection = null, RuntimeOptions runtime = null, + public static StackWrapperSettings With ( + InjectionOptions injection = null, RuntimeOptions runtime = null, MaskOptions mask = null, VersioningOptions versioning = null ) { return new StackWrapperSettings() diff --git a/StackInjector/Settings/VersioningOptions.cs b/StackInjector/Settings/VersioningOptions.cs index c6d62c7..7b18b56 100644 --- a/StackInjector/Settings/VersioningOptions.cs +++ b/StackInjector/Settings/VersioningOptions.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; +using System.Collections.Generic; using System.Reflection; -using System.Text; namespace StackInjector.Settings { @@ -43,9 +40,15 @@ internal VersioningOptions () { } /// - public object Clone () => this.MemberwiseClone(); + public object Clone () + { + return this.MemberwiseClone(); + } - IOptions IOptions.CreateDefault () => Default; + IOptions IOptions.CreateDefault () + { + return Default; + } @@ -79,7 +82,7 @@ public VersioningOptions AddAssembliesToLookup ( params Assembly[] assemblies ) return this; } - + #endregion From 5ab29f5dece4453ee72dc014dbf854af2ab2319d Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sat, 19 Jun 2021 12:55:50 +0200 Subject: [PATCH 04/17] Added more tests --- tests/StackInjector.TEST.BlackBox/Injector.cs | 38 +--- .../Injector_Async.cs | 190 ++++++++++++++++++ .../settings/Versioning.cs | 108 ++++++++++ 3 files changed, 301 insertions(+), 35 deletions(-) create mode 100644 tests/StackInjector.TEST.BlackBox/Injector_Async.cs create mode 100644 tests/StackInjector.TEST.BlackBox/settings/Versioning.cs diff --git a/tests/StackInjector.TEST.BlackBox/Injector.cs b/tests/StackInjector.TEST.BlackBox/Injector.cs index ff52bb2..3410b8a 100644 --- a/tests/StackInjector.TEST.BlackBox/Injector.cs +++ b/tests/StackInjector.TEST.BlackBox/Injector.cs @@ -129,52 +129,20 @@ public void AlwaysCreate () private class _ExternalAssemblyReference_Class {[Served] public readonly ExternalAssembly.Externalclass externalclass; } [Test] - public void ExternalAssembly_FromClass_NoVers () + public void ExternalAssembly_FromClass () { Assert.DoesNotThrow(() => Injector.From<_ExternalAssemblyReference_Class>()); } [Service] - private class _ExternalAssemblyReference_Interface {[Served] public readonly ExternalAssembly.IExternalClass externalclass; } + internal class _ExternalAssemblyReference_Interface {[Served] public readonly ExternalAssembly.IExternalClass externalclass; } [Test] - public void ExternalAssembly_FromInterface_NoVers () + public void ExternalAssembly_FromInterface () { Assert.DoesNotThrow(() => Injector.From<_ExternalAssemblyReference_Interface>()); } - - - - [Service(Version = 2.0)] - private class _ExternalAssemblyReference_Local : ExternalAssembly.IExternalClass - { - public void SomeMethod () => throw new NotImplementedException(); - } - - [Test] - public void ExternalAssembly_LocalImplementation_NoVers_Throws () - { - var settings = StackWrapperSettings.With( - mask: MaskOptions.BlackList - ); - settings.Mask.Add(typeof(ExternalAssembly.Externalclass)); - Assert.Throws( () => Injector.From<_ExternalAssemblyReference_Interface>(settings) ); - } - - [Test] - public void ExternalAssembly_LocalImplementation_Vers () - { - var settings = StackWrapperSettings.With( - mask: MaskOptions.BlackList - ); - settings.Mask.Add(typeof(ExternalAssembly.Externalclass)); - settings.Versioning.AddAssembliesToLookup(Assembly.GetExecutingAssembly()); - - var wrapper = Injector.From<_ExternalAssemblyReference_Interface>(settings); - Assert.IsInstanceOf<_ExternalAssemblyReference_Local>(wrapper.Entry.externalclass); - } - } } \ No newline at end of file diff --git a/tests/StackInjector.TEST.BlackBox/Injector_Async.cs b/tests/StackInjector.TEST.BlackBox/Injector_Async.cs new file mode 100644 index 0000000..074d984 --- /dev/null +++ b/tests/StackInjector.TEST.BlackBox/Injector_Async.cs @@ -0,0 +1,190 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using NUnit.Framework; +using StackInjector.Attributes; +using StackInjector.Core; +using StackInjector.Settings; +using CTkn = System.Threading.CancellationToken; + +namespace StackInjector.TEST.BlackBox +{ + [TestFixture] + public class Injector_Async + { + /*NOTE: AsyncStackWrapper is an extension od the normal wrapper, + * there is a common core logic; this means that the tests done in UseCases.Sync + * are also valid for the AsyncStackWrapper, since the tested code is the same + * (injection logic) + */ + + // base async test class + [Service] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822", Justification = "methods don't need to be static.")] + private class AsyncBase + { + internal async Task WaitForever ( object obj, CTkn tkn ) + { + // waits forever unless cancelled + await Task.Delay(-1, tkn); + return obj; + } + + internal async Task ReturnArg ( object obj, CTkn tkn ) + { + if ( tkn.IsCancellationRequested ) + return obj; + + await Task.CompletedTask; + return obj; + } + } + + + [Test] + public void SubmitNoElaboration () + { + using var wrapper = Injector.AsyncFrom( (b,i,t) => b.WaitForever(i,t) ); + wrapper.Submit(new object()); + + Assert.Multiple(() => + { + Assert.IsTrue(wrapper.AnyTaskLeft()); + Assert.IsFalse(wrapper.AnyTaskCompleted()); + }); + } + + [Test] + public void SubmitNoCatch () + { + var wrapper = Injector.AsyncFrom( (b,i,t) => b.ReturnArg(i,t) ); + + var task = wrapper.SubmitAndGet(new object()); + task.Wait(); + + Assert.Multiple(() => + { + Assert.IsTrue(wrapper.AnyTaskLeft()); + Assert.IsTrue(wrapper.AnyTaskCompleted()); + }); + } + + + [Test] + public async Task SubmitAndCatchAsyncEnumerable () + { + var wrapper = Injector.AsyncFrom( (b,i,t) => b.ReturnArg(i,t) ); + object + obj1 = new(), + obj2 = new(); + + wrapper.Submit(obj1); + wrapper.Submit(obj2); + + var objs = new List(); + var count = 0; + + await foreach ( var obj in wrapper.Elaborated() ) + { + objs.Add(obj); + if ( ++count > 2 ) + break; + } + + Assert.Multiple(() => + { + Assert.IsFalse(wrapper.AnyTaskLeft()); + CollectionAssert.AreEquivalent(new object[] { obj1, obj2 }, objs); + }); + + } + + + [Test] + [Timeout(1000)] + [Retry(3)] + public void TaskCancellation () + { + var wrapper = Injector.AsyncFrom( (b,i,t) => b.WaitForever(i,t) ); + var task = wrapper.SubmitAndGet(new object()); + var tkn = wrapper.PendingTasksCancellationToken; + + Assume.That(!tkn.IsCancellationRequested); + + var elaborationTask = wrapper.Elaborate(); + + wrapper.Dispose(); + + Assert.Multiple(() => + { + Assert.That(tkn.IsCancellationRequested); + var aggregate = Assert.Throws(()=>task.Wait()); + Assert.IsInstanceOf(aggregate.InnerException); + }); + } + + + + [Test] + public void ThrowsInvalidOnMultipleElaboration () + { + using var wrapper = Injector.AsyncFrom( (b,i,t) => b.WaitForever(i,t) ); + wrapper.Submit(new object()); + + wrapper.Elaborate(); + + Assert.Multiple(() => + { + Assert.IsTrue(wrapper.IsElaborating); + var aggregate = Assert.Throws(() => wrapper.Elaborate().Wait()); + Assert.IsInstanceOf(aggregate.InnerException); + }); + + + } + + + [Test] + [Timeout(1000)] + public void SubmitWithEvent () + { + using var wrapper = Injector.AsyncFrom( + (b,i,t) => b.ReturnArg(i,t), + StackWrapperSettings.With( + runtime: + RuntimeOptions.Default + .WhenNoMoreTasks(AsyncWaitingMethod.Wait,100) + ) + ); + + // test holders + var semaphore = new SemaphoreSlim(0); + + object + token = new(), + tokentest = null; + IStackWrapperCore wrappertest = null; + + wrapper.OnElaborated += ( sender, args ) => + { + tokentest = args.Result; + wrappertest = (IStackWrapperCore)sender; + semaphore.Release(); + }; + + wrapper.Elaborate(); + + Assert.Multiple(async () => + { + await wrapper.SubmitAndGet(token); + await semaphore.WaitAsync(); + Assert.AreSame(token, tokentest); + Assert.AreSame(wrapper, wrappertest); + }); + } + + } +} diff --git a/tests/StackInjector.TEST.BlackBox/settings/Versioning.cs b/tests/StackInjector.TEST.BlackBox/settings/Versioning.cs new file mode 100644 index 0000000..b6b0caf --- /dev/null +++ b/tests/StackInjector.TEST.BlackBox/settings/Versioning.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using StackInjector.Attributes; +using StackInjector.Settings; +using StackInjector.TEST.Structures.Simple; +using static StackInjector.TEST.BlackBox.Injection; + +namespace StackInjector.TEST.BlackBox +{ + + #pragma warning disable 0649 + + [TestFixture] + class Versioning + { + #region maj min exact + + [Service] private class VersionClass {[Served] internal Level1_11 Level; } + + [Test] + public void ServedVersioningClass () + { + var settings = StackWrapperSettings.Default; + settings.Versioning + .VersioningMethod(ServedVersionTargetingMethod.LatestMajor, true); + + /* CLASSES ARE NOT VERSIONED, ONLY INTERFACES */ + Assert.IsInstanceOf( + Injector.From(settings).Entry.Level + ); + + } + + [Service] private class VersionInterface {[Served(TargetVersion = 1.0)] public ILevel1 level1; } + + [Test] + public void ServedVersioningInterface () + { + var versionedService = Injector.From().Entry.level1; + + Assert.IsInstanceOf(versionedService); + } + + + [Test] + public void SettingVersioningLatestMaj () + { + var settings = StackWrapperSettings.Default; + settings.Versioning + .VersioningMethod(ServedVersionTargetingMethod.LatestMajor, true); + + var versionedService = Injector.From( settings ).Entry.level1; + + Assert.IsInstanceOf(versionedService); + } + + + [Test] + public void SettingVersioningLatestMin () + { + var settings = StackWrapperSettings.Default; + settings.Versioning + .VersioningMethod(ServedVersionTargetingMethod.LatestMinor, true); + + var versionedService = Injector.From( settings ).Entry.level1; + + Assert.IsInstanceOf(versionedService); + } + + #endregion + + + [Service(Version = 2.0)] + private class _ExternalAssemblyReference_Local : ExternalAssembly.IExternalClass + { + public void SomeMethod () => throw new NotImplementedException(); + } + + [Test] + public void ExternalAssembly_LocalImplementation_Throws () + { + var settings = StackWrapperSettings.With( + mask: MaskOptions.BlackList + ); + settings.Mask.Add(typeof(ExternalAssembly.Externalclass)); + Assert.Throws(() => Injector.From<_ExternalAssemblyReference_Interface>(settings)); + } + + [Test] + public void ExternalAssembly_LocalImplementation_Vers () + { + var settings = StackWrapperSettings.With( + mask: MaskOptions.BlackList + ); + settings.Mask.Add(typeof(ExternalAssembly.Externalclass)); + settings.Versioning.AddAssembliesToLookup(Assembly.GetExecutingAssembly()); + + var wrapper = Injector.From<_ExternalAssemblyReference_Interface>(settings); + Assert.IsInstanceOf<_ExternalAssemblyReference_Local>(wrapper.Entry.externalclass); + } + + } +} From 867a96d0b5b91fca6598c0694d050e403e2e3d4e Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sun, 20 Jun 2021 17:34:49 +0200 Subject: [PATCH 05/17] implemented #170 - added `AddInterfaceBinding`, `RemoveInterfaceBinding` to VersioningOptions - updated internal reflection and versioning logic - added test --- .../InjectionCore/InjectionCore.reflection.cs | 30 ++++------ .../InjectionCore/InjectionCore.versioning.cs | 11 ++++ StackInjector/Settings/VersioningOptions.cs | 56 ++++++++++++++++++- .../settings/Versioning.cs | 19 ++++++- 4 files changed, 94 insertions(+), 22 deletions(-) diff --git a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs index 05741b2..c6c20dc 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs @@ -14,29 +14,21 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr { if ( type.IsInterface ) { - IEnumerable versions = this.instances.TypesAssignableFrom(type); + IEnumerable versions = this.Version(type, servedAttribute); - // has an implementation for the interface already been found? if ( versions.Any() ) { - return versions.First(); + //todo check for multiple valid versions + var t = versions.First(); + MaskPass(t); + return t; } + + if ( servedAttribute is null ) + throw new ImplementationNotFoundException(type, $"can't find [Service] for interface {type.Name}"); else - { - versions = this.Version(type, servedAttribute); - if ( versions.Any() ) - { - //todo check for multiple valid versions - var t = versions.First(); - MaskPass(t); - return t; - } - - if ( servedAttribute is null ) - throw new ImplementationNotFoundException(type, $"can't find [Service] for interface {type.Name}"); - else - throw new ImplementationNotFoundException(type, $"can't find [Service] for {type.Name} v{servedAttribute.TargetVersion}"); - } + throw new ImplementationNotFoundException(type, $"can't find [Service] for {type.Name} v{servedAttribute.TargetVersion}"); + } else { @@ -44,7 +36,7 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr return type; } - + // exception check and thrower void MaskPass ( Type type ) { if ( this.settings.Mask.IsMasked(type) ) //todo create custom exception diff --git a/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs index 481c535..bcaf55e 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs @@ -9,9 +9,20 @@ namespace StackInjector.Core { internal partial class InjectionCore { + private static readonly Type _istackwrappercore = typeof(IStackWrapperCore); + // performs versioning on the specified type private IEnumerable Version ( Type targetType, ServedAttribute servedAttribute ) { + if (targetType.IsSubclassOf( _istackwrappercore ) || targetType == _istackwrappercore) + return this.instances.TypesAssignableFrom(targetType); + + if (this.settings.Versioning._customBindings != null && + this.settings.Versioning._customBindings.TryGetValue(targetType,out var t) ) + { + return Enumerable.Repeat(t, 1); + } + var targetVersion = servedAttribute?.TargetVersion ?? 0.0; var method = diff --git a/StackInjector/Settings/VersioningOptions.cs b/StackInjector/Settings/VersioningOptions.cs index 7b18b56..05c805b 100644 --- a/StackInjector/Settings/VersioningOptions.cs +++ b/StackInjector/Settings/VersioningOptions.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Reflection; namespace StackInjector.Settings @@ -13,11 +14,15 @@ public sealed class VersioningOptions : IOptions internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; internal bool _overrideTargetingMethod; + internal Dictionary _customBindings; + /// /// A set of assemblies overriding where to look up types in, when not empty. /// public HashSet AssemblyLookUpOrder { get; private set; } = new HashSet(); + + internal VersioningOptions () { } @@ -72,7 +77,7 @@ public VersioningOptions VersioningMethod ( ServedVersionTargetingMethod targetM /// add a range of assemblies from which, in order, look for types when injecting interfaces, overriding any default option. /// /// - /// + /// the modified options public VersioningOptions AddAssembliesToLookup ( params Assembly[] assemblies ) { foreach ( var a in assemblies ) @@ -82,6 +87,53 @@ public VersioningOptions AddAssembliesToLookup ( params Assembly[] assemblies ) return this; } + #region bindings + + /// + /// binds the specified implementation with the interface, ensuring that versioning + /// the specified interface will always return the wanted implementation. + /// + /// Must be an interface type. + /// The implementation type for the type + /// the modified options + public VersioningOptions AddInterfaceBinding () + where TImpl : class, new() + { + var ti = typeof(TInterface); + if ( !ti.IsInterface ) + { + throw new ArgumentException($"{ti.FullName} is not an interface!"); + } + + if ( this._customBindings == null ) + this._customBindings = new Dictionary(); + + this._customBindings.Add(typeof(TInterface), typeof(TImpl)); + return this; + } + + /// + /// removes the specified interface type. + /// + /// the modified options + public VersioningOptions RemoveInterfaceBinding () + { + this._customBindings.Remove(typeof(TInterface)); + return this; + } + + /// + /// removes all interface bindings + /// + /// the modified options + public VersioningOptions RemoveInterfaceBinding () + { + this._customBindings.Clear(); + this._customBindings = null; + return this; + } + + #endregion #endregion diff --git a/tests/StackInjector.TEST.BlackBox/settings/Versioning.cs b/tests/StackInjector.TEST.BlackBox/settings/Versioning.cs index b6b0caf..15d2e2a 100644 --- a/tests/StackInjector.TEST.BlackBox/settings/Versioning.cs +++ b/tests/StackInjector.TEST.BlackBox/settings/Versioning.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using StackInjector.Attributes; using StackInjector.Settings; +using StackInjector.TEST.ExternalAssembly; using StackInjector.TEST.Structures.Simple; using static StackInjector.TEST.BlackBox.Injection; @@ -97,12 +98,28 @@ public void ExternalAssembly_LocalImplementation_Vers () var settings = StackWrapperSettings.With( mask: MaskOptions.BlackList ); - settings.Mask.Add(typeof(ExternalAssembly.Externalclass)); + settings.Mask.Add(typeof(Externalclass)); settings.Versioning.AddAssembliesToLookup(Assembly.GetExecutingAssembly()); var wrapper = Injector.From<_ExternalAssemblyReference_Interface>(settings); Assert.IsInstanceOf<_ExternalAssemblyReference_Local>(wrapper.Entry.externalclass); } + [Test] + public void ExternalAssembly_LocalImplementation_Bind () + { + var settings = StackWrapperSettings.With( + mask: MaskOptions.BlackList + ); + settings.Mask + .Add(typeof(Externalclass)); + settings.Versioning + .AddAssembliesToLookup(typeof(IExternalClass).Assembly) + .AddInterfaceBinding(); + + var wrapper = Injector.From<_ExternalAssemblyReference_Interface>(settings); + Assert.IsInstanceOf<_ExternalAssemblyReference_Local>(wrapper.Entry.externalclass); + } + } } From 389ee284f4e8e3bcd40186c49f415f1ad8b315fe Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sun, 20 Jun 2021 17:42:54 +0200 Subject: [PATCH 06/17] Fixed inconsistent behaviour of CountServices --- StackInjector/Core/InstancesHolder.cs | 3 ++- StackInjector/Core/StackWrapperCore.cs | 2 +- tests/StackInjector.TEST.BlackBox/Behaviour.cs | 2 +- tests/StackInjector.TEST.BlackBox/Cloning.cs | 2 +- tests/StackInjector.TEST.BlackBox/Injector.cs | 4 ++-- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/StackInjector/Core/InstancesHolder.cs b/StackInjector/Core/InstancesHolder.cs index f3114df..2077df5 100644 --- a/StackInjector/Core/InstancesHolder.cs +++ b/StackInjector/Core/InstancesHolder.cs @@ -27,11 +27,12 @@ internal bool AddType ( Type type ) return this.TryAdd(type, new LinkedList()); } - internal void CountAllInstances () + internal int CountAllInstances () { this.total_count = 0; foreach ( var pair in this ) this.total_count += pair.Value.Count; + return this.total_count; } diff --git a/StackInjector/Core/StackWrapperCore.cs b/StackInjector/Core/StackWrapperCore.cs index 9a96bdd..cfb5188 100644 --- a/StackInjector/Core/StackWrapperCore.cs +++ b/StackInjector/Core/StackWrapperCore.cs @@ -40,7 +40,7 @@ public IEnumerable GetServices () public int CountServices () { - return this.Core.instances.total_count; + return this.Core.instances.CountAllInstances(); } public IClonedCore CloneCore ( StackWrapperSettings settings = null ) diff --git a/tests/StackInjector.TEST.BlackBox/Behaviour.cs b/tests/StackInjector.TEST.BlackBox/Behaviour.cs index 070afab..ce99061 100644 --- a/tests/StackInjector.TEST.BlackBox/Behaviour.cs +++ b/tests/StackInjector.TEST.BlackBox/Behaviour.cs @@ -26,7 +26,7 @@ public void Avoid_CircularReference () Assert.Multiple(() => { Assert.AreSame(wrapper.Entry, wrapper.Entry.loopB.loopA); - Assert.AreEqual(2, wrapper.CountServices()); + Assert.AreEqual(3, wrapper.CountServices()); }); } diff --git a/tests/StackInjector.TEST.BlackBox/Cloning.cs b/tests/StackInjector.TEST.BlackBox/Cloning.cs index 35c38bf..d877657 100644 --- a/tests/StackInjector.TEST.BlackBox/Cloning.cs +++ b/tests/StackInjector.TEST.BlackBox/Cloning.cs @@ -107,7 +107,7 @@ public void Deep_RemoveUnused () Assert.Multiple(() => { var wrap = Injector.From( ); - Assert.AreEqual(4, wrap.CountServices()); + Assert.AreEqual(5, wrap.CountServices()); // base is removed after injecting from a class that doesn't need it var clone = wrap.DeepCloneCore( settings ).ToWrapper( ); diff --git a/tests/StackInjector.TEST.BlackBox/Injector.cs b/tests/StackInjector.TEST.BlackBox/Injector.cs index 3410b8a..1ca42ae 100644 --- a/tests/StackInjector.TEST.BlackBox/Injector.cs +++ b/tests/StackInjector.TEST.BlackBox/Injector.cs @@ -32,7 +32,7 @@ public void From_Class () Assert.That(entry.level1A, Is.Not.Null.And.InstanceOf()); Assert.That(entry.level1B, Is.Not.Null.And.InstanceOf()); Assert.AreSame(entry.level1A.level2, entry.level1B.level2); - Assert.AreEqual(4, wrapper.CountServices()); + Assert.AreEqual(5, wrapper.CountServices()); // 4 classes + 1 wrapper }); } @@ -50,7 +50,7 @@ public void From_Interface () Assert.That(_entry.level1A, Is.Not.Null.And.InstanceOf()); Assert.That(_entry.level1B, Is.Not.Null.And.InstanceOf()); Assert.AreSame(_entry.level1A.level2, _entry.level1B.level2); - Assert.AreEqual(4, wrapper.CountServices()); + Assert.AreEqual(5, wrapper.CountServices()); // 4 classes + 1 wrapper }); } From 1ded7fb697e39068fafa93d4af6611b9f482ee8b Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sun, 20 Jun 2021 17:48:04 +0200 Subject: [PATCH 07/17] fixed typos and removed zombies --- StackInjector/Core/IStackWrapperCore.cs | 3 +-- .../InjectionCore/InjectionCore.instantiation.cs | 3 --- StackInjector/Settings/MaskOptions.cs | 2 +- tests/StackInjector.TEST.BlackBox/Cloning.cs | 15 ++------------- 4 files changed, 4 insertions(+), 19 deletions(-) diff --git a/StackInjector/Core/IStackWrapperCore.cs b/StackInjector/Core/IStackWrapperCore.cs index 4eb9a3f..3ee2daf 100644 --- a/StackInjector/Core/IStackWrapperCore.cs +++ b/StackInjector/Core/IStackWrapperCore.cs @@ -24,10 +24,9 @@ public interface IStackWrapperCore : IDisposable, ICloneableCore /// IEnumerable GetServices (); - //! description is wrong /// /// The current number of all tracked services.
- /// Does also include the Wrapper, so if you want all the instances + /// Does also include the Wrapper, so if you want just the instances /// wrapper.CountServices()-1 ///
int CountServices (); diff --git a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs index 415b1d8..c6b1bac 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs @@ -17,9 +17,6 @@ private object OfTypeOrInstantiate ( Type type ) if ( serviceAtt == null ) throw new NotAServiceException(type, $"Type {type.FullName} is not a [Service]"); - ////if( !this.instances.ContainsKey(type) ) - //// throw new ServiceNotFoundException(type, $"The type {type.FullName} is not in a registred assembly!"); - return serviceAtt.Pattern switch { diff --git a/StackInjector/Settings/MaskOptions.cs b/StackInjector/Settings/MaskOptions.cs index d0e330b..b395fe4 100644 --- a/StackInjector/Settings/MaskOptions.cs +++ b/StackInjector/Settings/MaskOptions.cs @@ -68,7 +68,7 @@ public object Clone () public static MaskOptions WhiteList => new MaskOptions() { _isWhiteList = true }; /// - /// allow every type except the regisred ones. + /// allow every type except the registred ones. /// public static MaskOptions BlackList => new MaskOptions(); diff --git a/tests/StackInjector.TEST.BlackBox/Cloning.cs b/tests/StackInjector.TEST.BlackBox/Cloning.cs index d877657..77b198c 100644 --- a/tests/StackInjector.TEST.BlackBox/Cloning.cs +++ b/tests/StackInjector.TEST.BlackBox/Cloning.cs @@ -1,11 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Linq; using NUnit.Framework; -using StackInjector.Attributes; -using StackInjector.Core; using StackInjector.Exceptions; using StackInjector.Settings; using StackInjector.TEST.Structures.Simple; @@ -17,11 +11,6 @@ namespace StackInjector.TEST.BlackBox public class Cloning { - //? might be used for exception asserting - //var iete = Assert.Throws(() => wrapperA.Entry.Logic() ); - //Assert.IsInstanceOf(iete.InnerException); - //StringAssert.Contains("No instance found", iete.Message); - #pragma warning disable 0649 #region Simple cloning @@ -97,7 +86,7 @@ public void Deep_IsDifferentCore () }); } - [Test] //? perhaps move to Settings + [Test] public void Deep_RemoveUnused () { var settings = StackWrapperSettings.Default; From 2a6b4644397eabbeb0f8947cb2d7b8fcc877290c Mon Sep 17 00:00:00 2001 From: Jacopo Date: Tue, 29 Jun 2021 10:46:03 +0200 Subject: [PATCH 08/17] Update InjectionCore.reflection.cs --- .../Core/InjectionCore/InjectionCore.reflection.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs index c6c20dc..bb2a567 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs @@ -20,7 +20,7 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr { //todo check for multiple valid versions var t = versions.First(); - MaskPass(t); + _MaskPass(t); return t; } @@ -32,12 +32,12 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr } else { - MaskPass(type); + _MaskPass(type); return type; } // exception check and thrower - void MaskPass ( Type type ) + void _MaskPass ( Type type ) { if ( this.settings.Mask.IsMasked(type) ) //todo create custom exception throw new InvalidOperationException($"Type {type.Name} is { (this.settings.Mask._isWhiteList ? "not whitelisted" : "blacklisted")}"); From 080c76f32c932d636297807147d53ffe3555f2df Mon Sep 17 00:00:00 2001 From: Jacopo Date: Tue, 29 Jun 2021 11:39:34 +0200 Subject: [PATCH 09/17] slight performance improvements --- .../InjectionCore/InjectionCore.injection.cs | 16 ++--- .../Settings/StackWrapperSettings.cs | 60 ++++++++++++------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/StackInjector/Core/InjectionCore/InjectionCore.injection.cs b/StackInjector/Core/InjectionCore/InjectionCore.injection.cs index 307fda8..1f8c801 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.injection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.injection.cs @@ -54,10 +54,10 @@ private void InjectFields ( Type type, object instance, ref List used, b { var fields = type.GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ) - .Where( f => f.GetCustomAttribute() is null ); - - if ( strict ) - fields = fields.Where(field => field.GetCustomAttribute() != null); + .Where( f => + f.GetCustomAttribute() is null + && (!strict||f.GetCustomAttribute() != null) //if not strict, skip this check + ); foreach ( var serviceField in fields ) { @@ -78,10 +78,10 @@ private void InjectProperties ( Type type, object instance, ref List use { var properties = type.GetProperties( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ) - .Where( p => p.GetCustomAttribute() is null ); - - if ( strict ) - properties = properties.Where(property => property.GetCustomAttribute() != null); + .Where( p => + p.GetCustomAttribute() is null + && (!strict || p.GetCustomAttribute() != null) //if not strict, skip this check + ); foreach ( var serviceProperty in properties ) { diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 912f6da..20bc848 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -31,7 +31,17 @@ public sealed partial class StackWrapperSettings - private StackWrapperSettings () { } + private StackWrapperSettings ( + MaskOptions mo, + InjectionOptions io, + VersioningOptions vo, + RuntimeOptions ro ) + { + this.Mask = mo; + this.Injection = io; + this.Versioning = vo; + this.Runtime = ro; + } @@ -57,7 +67,12 @@ public StackWrapperSettings Clone () /// /// /// - public static StackWrapperSettings Default => With(); + public static StackWrapperSettings Default => new StackWrapperSettings( + MaskOptions.Disabled, + InjectionOptions.Default, + VersioningOptions.Default, + RuntimeOptions.Default + ); /// @@ -69,16 +84,17 @@ public StackWrapperSettings Clone () /// versioning options /// public static StackWrapperSettings With ( - InjectionOptions injection = null, RuntimeOptions runtime = null, - MaskOptions mask = null, VersioningOptions versioning = null ) + InjectionOptions injection = null, + RuntimeOptions runtime = null, + MaskOptions mask = null, + VersioningOptions versioning = null ) { - return new StackWrapperSettings() - { - Mask = mask ?? MaskOptions.Disabled, - Injection = injection ?? InjectionOptions.Default, - Runtime = runtime ?? RuntimeOptions.Default, - Versioning = versioning ?? VersioningOptions.Default - }; + return new StackWrapperSettings( + mask ?? MaskOptions.Disabled, + injection ?? InjectionOptions.Default, + versioning ?? VersioningOptions.Default, + runtime ?? RuntimeOptions.Default + ); } @@ -87,18 +103,16 @@ public static StackWrapperSettings With ( /// everything is served by default, and you must instead use [Ignored] on properties and fields you don't want injected /// /// - public static StackWrapperSettings DefaultBySubtraction => - With( - injection: - InjectionOptions.Default - .ServingMethod(ServeAll, true), - mask: - null, - runtime: - null, - versioning: - null - ); + public static StackWrapperSettings DefaultBySubtraction + { + get + { + var settings = Default; + settings.Injection + .ServingMethod(ServeAll, true); + return settings; + } + } } From 686930f71341af07e82f774f3453bc0d0bd447ca Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sat, 3 Jul 2021 11:38:34 +0200 Subject: [PATCH 10/17] AsyncStackWrapperCore optimizations reached 50 tests yay --- .../Core/AsyncStackWrapperCore.logic.cs | 47 +++++++------------ .../Injector_Async.cs | 23 +++++++++ 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/StackInjector/Core/AsyncStackWrapperCore.logic.cs b/StackInjector/Core/AsyncStackWrapperCore.logic.cs index d4f2a7b..795f57c 100644 --- a/StackInjector/Core/AsyncStackWrapperCore.logic.cs +++ b/StackInjector/Core/AsyncStackWrapperCore.logic.cs @@ -40,7 +40,13 @@ public bool AnyTaskCompleted () public async IAsyncEnumerable Elaborated () { - this.EnsureExclusiveExecution(true); + // begin elaboration + lock ( this._listAccessLock ) + { + if ( this._exclusiveExecution ) + throw new InvalidOperationException(); + this._exclusiveExecution = true; + } while ( !this.cancelPendingTasksSource.IsCancellationRequested ) { @@ -62,6 +68,7 @@ public async IAsyncEnumerable Elaborated () } } + // no more elaborating lock ( this._listAccessLock ) this._exclusiveExecution = false; @@ -77,50 +84,28 @@ public async Task Elaborate () // true if outher loop is to break private async Task OnNoTasksLeft () { - // to not repeat code - Task listAwaiter () - { - return this._emptyListAwaiter.WaitAsync(); - } - switch ( this.Settings.Runtime._asyncWaitingMethod ) { case AsyncWaitingMethod.Exit: default: - return true; case AsyncWaitingMethod.Wait: - // wait for a signal of the list not being empty anymore - await listAwaiter().ConfigureAwait(true); + await this._emptyListAwaiter.WaitAsync().ConfigureAwait(true); return false; case AsyncWaitingMethod.Timeout: - var list = listAwaiter(); - var timeout = Task.Delay( this.Settings.Runtime._asyncWaitTime ); - - // if the timeout elapses first, then stop waiting - return (await Task.WhenAny(list, timeout).ConfigureAwait(true)) == timeout; + return !await + this._emptyListAwaiter.WaitAsync( + this.Settings.Runtime._asyncWaitTime, + this.PendingTasksCancellationToken + ) + .ConfigureAwait(true); } } - - private void EnsureExclusiveExecution ( bool set = false ) - { - lock ( this._listAccessLock ) // reused lock - { - if ( this._exclusiveExecution ) - throw new InvalidOperationException(); - - if ( set ) - this._exclusiveExecution = set; - } - } - - - } -} \ No newline at end of file +} diff --git a/tests/StackInjector.TEST.BlackBox/Injector_Async.cs b/tests/StackInjector.TEST.BlackBox/Injector_Async.cs index 074d984..feb72a6 100644 --- a/tests/StackInjector.TEST.BlackBox/Injector_Async.cs +++ b/tests/StackInjector.TEST.BlackBox/Injector_Async.cs @@ -57,6 +57,7 @@ public void SubmitNoElaboration () }); } + [Test] public void SubmitNoCatch () { @@ -186,5 +187,27 @@ public void SubmitWithEvent () }); } + + [Test] + [Timeout(100)] + public void StopOnTimeout () + { + var wrapper = Injector.AsyncFrom( + (b,i,t) => b.ReturnArg(i,t), + StackWrapperSettings.With( + runtime: + RuntimeOptions.Default + .WhenNoMoreTasks(AsyncWaitingMethod.Timeout,1) + ) + ); + + Assume.That(!wrapper.IsElaborating); + + wrapper.Elaborate().Wait(); + + Assert.That(!wrapper.IsElaborating && !wrapper.AnyTaskLeft()); + + } + } } From a1ba78655fcc57130584cd086d12aa3def78a167 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sat, 3 Jul 2021 12:28:38 +0200 Subject: [PATCH 11/17] Update Injector_Async.cs --- tests/StackInjector.TEST.BlackBox/Injector_Async.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/StackInjector.TEST.BlackBox/Injector_Async.cs b/tests/StackInjector.TEST.BlackBox/Injector_Async.cs index feb72a6..f7025ef 100644 --- a/tests/StackInjector.TEST.BlackBox/Injector_Async.cs +++ b/tests/StackInjector.TEST.BlackBox/Injector_Async.cs @@ -157,7 +157,7 @@ public void SubmitWithEvent () StackWrapperSettings.With( runtime: RuntimeOptions.Default - .WhenNoMoreTasks(AsyncWaitingMethod.Wait,100) + .WhenNoMoreTasks(AsyncWaitingMethod.Wait,-1) ) ); From 6c071fd0693e3d1ac7fd98118ebb0442c163cd33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Jun 2021 05:01:03 +0000 Subject: [PATCH 12/17] Bump NUnit3TestAdapter in /tests/StackInjector.TEST.BlackBox Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 3.17.0 to 4.0.0. - [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases) - [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V3.17...V4.0.0) --- updated-dependencies: - dependency-name: NUnit3TestAdapter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] From 386d07279f87b367db26c44c2eef6063bc0792b6 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sat, 21 Aug 2021 03:28:58 +0200 Subject: [PATCH 13/17] remove type passing in wrappers --- StackInjector/Core/AsyncStackWrapperCore.cs | 2 +- StackInjector/Core/StackWrapperCore.cs | 9 +++++---- StackInjector/Wrappers/AsyncStackWrapper.cs | 4 ++-- StackInjector/Wrappers/StackWrapper.cs | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/StackInjector/Core/AsyncStackWrapperCore.cs b/StackInjector/Core/AsyncStackWrapperCore.cs index a3921f0..5e6644f 100644 --- a/StackInjector/Core/AsyncStackWrapperCore.cs +++ b/StackInjector/Core/AsyncStackWrapperCore.cs @@ -34,7 +34,7 @@ public CancellationToken PendingTasksCancellationToken // register an event that in case the list is empty, release the empty event listener. - internal AsyncStackWrapperCore ( InjectionCore core, Type toRegister ) : base(core, toRegister) + internal AsyncStackWrapperCore ( InjectionCore core) : base(core) { this.cancelPendingTasksSource.Token.Register(this.ReleaseListAwaiter); } diff --git a/StackInjector/Core/StackWrapperCore.cs b/StackInjector/Core/StackWrapperCore.cs index cfb5188..00b5b9f 100644 --- a/StackInjector/Core/StackWrapperCore.cs +++ b/StackInjector/Core/StackWrapperCore.cs @@ -18,14 +18,15 @@ public ref readonly StackWrapperSettings Settings private protected readonly InjectionCore Core; - public StackWrapperCore ( InjectionCore core, Type toRegister ) + public StackWrapperCore ( InjectionCore core ) { this.Core = core; // add this wrapper to possible instances - if ( !this.Core.instances.AddType(toRegister) ) - this.Core.instances[toRegister].Clear(); - this.Core.instances[toRegister].AddFirst(this); + var registerAs = this.GetType(); + if ( !this.Core.instances.AddType(registerAs) ) + this.Core.instances[registerAs].Clear(); + this.Core.instances[registerAs].AddFirst(this); } diff --git a/StackInjector/Wrappers/AsyncStackWrapper.cs b/StackInjector/Wrappers/AsyncStackWrapper.cs index e4f7111..b92215f 100644 --- a/StackInjector/Wrappers/AsyncStackWrapper.cs +++ b/StackInjector/Wrappers/AsyncStackWrapper.cs @@ -16,8 +16,8 @@ public TEntry Entry this.Core.GetEntryPoint(); - public AsyncStackWrapper ( InjectionCore core ) : base(core, typeof(AsyncStackWrapper)) - { } + public AsyncStackWrapper ( InjectionCore core ) : base(core) { } + public void Submit ( TIn item ) { diff --git a/StackInjector/Wrappers/StackWrapper.cs b/StackInjector/Wrappers/StackWrapper.cs index 0817566..3978d18 100644 --- a/StackInjector/Wrappers/StackWrapper.cs +++ b/StackInjector/Wrappers/StackWrapper.cs @@ -9,7 +9,7 @@ namespace StackInjector.Wrappers internal class StackWrapper : StackWrapperCore, IStackWrapper { - internal StackWrapper ( InjectionCore core ) : base(core, typeof(StackWrapper)) { } + internal StackWrapper ( InjectionCore core ) : base(core) { } From 8453c76b6ac444ef4dd2df15a786e26c1cfea577 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sat, 21 Aug 2021 03:40:47 +0200 Subject: [PATCH 14/17] Exceptions refactoring removed ServiceNotFound and renamed MissingParameterlessConstructor into InvalidConstructor --- .../InjectionCore.instantiation.cs | 2 +- .../InjectionCore/InjectionCore.utilities.cs | 3 +-- .../Exceptions/InvalidConstructorException.cs | 22 +++++++++++++++++++ ...issingParameterlessConstructorException.cs | 22 ------------------- .../Exceptions/ServiceNotFoundException.cs | 19 ---------------- StackInjector/Injector.cs | 2 -- .../StackInjector.TEST.BlackBox/Exceptions.cs | 4 ++-- 7 files changed, 26 insertions(+), 48 deletions(-) create mode 100644 StackInjector/Exceptions/InvalidConstructorException.cs delete mode 100644 StackInjector/Exceptions/MissingParameterlessConstructorException.cs delete mode 100644 StackInjector/Exceptions/ServiceNotFoundException.cs diff --git a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs index c6b1bac..5c1b751 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs @@ -37,7 +37,7 @@ private object InstantiateService ( Type type ) //todo add more constructor options if ( type.GetConstructor(Array.Empty()) == null ) - throw new MissingParameterlessConstructorException(type, $"Missing parameteless constructor for {type.FullName}"); + throw new InvalidConstructorException(type, $"Missing parameteless constructor for {type.FullName}"); var instance = Activator.CreateInstance(type); diff --git a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs index 3e2af51..fc0ef48 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs @@ -16,8 +16,7 @@ internal T GetEntryPoint () : throw new InvalidEntryTypeException ( this.EntryType, - $"No instance found for entry type {this.EntryType.FullName}", - innerException: new ServiceNotFoundException(typeof(T), string.Empty) + $"No instance found for entry type {this.EntryType.FullName}" ); } diff --git a/StackInjector/Exceptions/InvalidConstructorException.cs b/StackInjector/Exceptions/InvalidConstructorException.cs new file mode 100644 index 0000000..755b690 --- /dev/null +++ b/StackInjector/Exceptions/InvalidConstructorException.cs @@ -0,0 +1,22 @@ +using System; + +namespace StackInjector.Exceptions +{ + /// + /// Thrown when a class has no parameterless constructor to call. + /// + public sealed class InvalidConstructorException : StackInjectorException + { + internal InvalidConstructorException () { } + + internal InvalidConstructorException ( Type type, string message ) : base(message) + { + this.SourceType = type; + } + + internal InvalidConstructorException ( string message ) : base(message) { } + + internal InvalidConstructorException ( string message, Exception innerException ) : base(message, innerException) { } + + } +} diff --git a/StackInjector/Exceptions/MissingParameterlessConstructorException.cs b/StackInjector/Exceptions/MissingParameterlessConstructorException.cs deleted file mode 100644 index 9f0febd..0000000 --- a/StackInjector/Exceptions/MissingParameterlessConstructorException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace StackInjector.Exceptions -{ - /// - /// Thrown when a class has no parameterless constructor to call. - /// - public sealed class MissingParameterlessConstructorException : StackInjectorException - { - internal MissingParameterlessConstructorException () { } - - internal MissingParameterlessConstructorException ( Type type, string message ) : base(message) - { - this.SourceType = type; - } - - internal MissingParameterlessConstructorException ( string message ) : base(message) { } - - internal MissingParameterlessConstructorException ( string message, Exception innerException ) : base(message, innerException) { } - - } -} diff --git a/StackInjector/Exceptions/ServiceNotFoundException.cs b/StackInjector/Exceptions/ServiceNotFoundException.cs deleted file mode 100644 index 619f93c..0000000 --- a/StackInjector/Exceptions/ServiceNotFoundException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -namespace StackInjector.Exceptions -{ - /// - /// Thrown when a type for a service has not been found. - /// - public sealed class ServiceNotFoundException : StackInjectorException - { - - internal ServiceNotFoundException ( Type type, string message ) : base(type, message) { } - - internal ServiceNotFoundException () { } - - internal ServiceNotFoundException ( string message ) : base(message) { } - - internal ServiceNotFoundException ( string message, Exception innerException ) : base(message, innerException) { } - } -} diff --git a/StackInjector/Injector.cs b/StackInjector/Injector.cs index 93e166d..f7bc8bb 100644 --- a/StackInjector/Injector.cs +++ b/StackInjector/Injector.cs @@ -24,7 +24,6 @@ public static partial class Injector /// The Initialized StackWrapper /// /// - /// /// /// public static IStackWrapper From ( StackWrapperSettings settings = null ) @@ -66,7 +65,6 @@ public static IStackWrapper From ( StackWrapperSettings settings = null ) /// The created asyncronous wrapper /// /// - /// /// /// public static IAsyncStackWrapper AsyncFrom diff --git a/tests/StackInjector.TEST.BlackBox/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/Exceptions.cs index 4e86e5c..4a147e7 100644 --- a/tests/StackInjector.TEST.BlackBox/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/Exceptions.cs @@ -45,7 +45,7 @@ private abstract class AbstractThrower { } [Test] public void ThrowsOnAbstractClass () { - Assert.Throws(() => Injector.From()); + Assert.Throws(() => Injector.From()); } @@ -72,7 +72,7 @@ private class BaseNoParameterlessConstructorThrower [Test] public void ThrowsMissingParameterlessConstructor () - => Assert.Throws(() => Injector.From()); + => Assert.Throws(() => Injector.From()); // ---------- From 6c1b46949e177054d5d9c6fb978d3174449acbe3 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sat, 21 Aug 2021 04:27:15 +0200 Subject: [PATCH 15/17] Simplified runtimesettings removed AsyncWaitingMethod and sobstituted with a single int --- .../Core/AsyncStackWrapperCore.logic.cs | 23 ++++----------- StackInjector/Settings/AsyncWaitingMethod.cs | 28 ------------------- StackInjector/Settings/RuntimeOptions.cs | 23 +++++++++------ .../Injector_Async.cs | 28 +++++++++---------- 4 files changed, 33 insertions(+), 69 deletions(-) delete mode 100644 StackInjector/Settings/AsyncWaitingMethod.cs diff --git a/StackInjector/Core/AsyncStackWrapperCore.logic.cs b/StackInjector/Core/AsyncStackWrapperCore.logic.cs index 795f57c..b62f92f 100644 --- a/StackInjector/Core/AsyncStackWrapperCore.logic.cs +++ b/StackInjector/Core/AsyncStackWrapperCore.logic.cs @@ -70,7 +70,9 @@ public async IAsyncEnumerable Elaborated () // no more elaborating lock ( this._listAccessLock ) + { this._exclusiveExecution = false; + } } @@ -84,28 +86,15 @@ public async Task Elaborate () // true if outher loop is to break private async Task OnNoTasksLeft () { - switch ( this.Settings.Runtime._asyncWaitingMethod ) - { - - case AsyncWaitingMethod.Exit: - default: - return true; + if ( this.Settings.Runtime._asyncWaitTime == 0 ) + return true; - case AsyncWaitingMethod.Wait: - // wait for a signal of the list not being empty anymore - await this._emptyListAwaiter.WaitAsync().ConfigureAwait(true); - return false; - - - case AsyncWaitingMethod.Timeout: - return !await - this._emptyListAwaiter.WaitAsync( + return !(await this._emptyListAwaiter.WaitAsync( this.Settings.Runtime._asyncWaitTime, this.PendingTasksCancellationToken ) - .ConfigureAwait(true); - } + .ConfigureAwait(true)); } } } diff --git a/StackInjector/Settings/AsyncWaitingMethod.cs b/StackInjector/Settings/AsyncWaitingMethod.cs deleted file mode 100644 index 1c7c6a8..0000000 --- a/StackInjector/Settings/AsyncWaitingMethod.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace StackInjector.Settings -{ - - /// - /// How an should behave when there are no pending tasks. - /// - public enum AsyncWaitingMethod - { - - /// - /// Simply exit the await foreach loop withouth doing anything - /// - Exit, - - /// - /// don't exit the loop, but wait for new Tasks to be submitted. - /// Exiting the loop requires Dispose() to be called on the wrapper or a break - /// - Wait, - - /// - /// don't immediately exit the loop, but rather wait a certain amount of time for - /// new tasks to be submitted tobefore exiting the loop - /// - Timeout - - } -} \ No newline at end of file diff --git a/StackInjector/Settings/RuntimeOptions.cs b/StackInjector/Settings/RuntimeOptions.cs index 3b53477..3f65e4f 100644 --- a/StackInjector/Settings/RuntimeOptions.cs +++ b/StackInjector/Settings/RuntimeOptions.cs @@ -1,4 +1,6 @@ -namespace StackInjector.Settings +using System; + +namespace StackInjector.Settings { /// /// Options used at runtime @@ -7,8 +9,7 @@ public sealed class RuntimeOptions : IOptions { // async management - internal AsyncWaitingMethod _asyncWaitingMethod = AsyncWaitingMethod.Exit; - internal int _asyncWaitTime = 500; + internal int _asyncWaitTime; // 0 internal RuntimeOptions () { } @@ -30,8 +31,8 @@ public object Clone () /// Default runtime options. Settings are valorized as following: /// /// - /// - /// , 500 + /// + /// -1 /// /// /// @@ -44,12 +45,16 @@ public object Clone () /// What to do when an /// has no more pending tasks to execute /// - /// the new waiting method - /// if is set, this will be max time to wait + /// this will be max time to wait.
+ /// -1: wait forever
+ /// 0: exit immediatly
+ /// +n: wait specified timeout (in ms)
/// the modified settings - public RuntimeOptions WhenNoMoreTasks ( AsyncWaitingMethod waitingMethod, int waitTime ) + public RuntimeOptions WaitTimeout ( int waitTime = 0 ) { - this._asyncWaitingMethod = waitingMethod; + if ( waitTime < -1 ) + throw new ArgumentOutOfRangeException(nameof(waitTime), $"{waitTime} cannot be below -1!"); + this._asyncWaitTime = waitTime; return this; } diff --git a/tests/StackInjector.TEST.BlackBox/Injector_Async.cs b/tests/StackInjector.TEST.BlackBox/Injector_Async.cs index f7025ef..33842be 100644 --- a/tests/StackInjector.TEST.BlackBox/Injector_Async.cs +++ b/tests/StackInjector.TEST.BlackBox/Injector_Async.cs @@ -74,6 +74,7 @@ public void SubmitNoCatch () } + [Timeout(1000)] [Test] public async Task SubmitAndCatchAsyncEnumerable () { @@ -150,15 +151,13 @@ public void ThrowsInvalidOnMultipleElaboration () [Test] [Timeout(1000)] - public void SubmitWithEvent () + public async Task SubmitWithEvent () { using var wrapper = Injector.AsyncFrom( (b,i,t) => b.ReturnArg(i,t), StackWrapperSettings.With( - runtime: - RuntimeOptions.Default - .WhenNoMoreTasks(AsyncWaitingMethod.Wait,-1) - ) + runtime: RuntimeOptions.Default + .WaitTimeout(-1)) ); // test holders @@ -176,20 +175,19 @@ public void SubmitWithEvent () semaphore.Release(); }; - wrapper.Elaborate(); + var eltask = wrapper.Elaborate(); - Assert.Multiple(async () => - { - await wrapper.SubmitAndGet(token); - await semaphore.WaitAsync(); - Assert.AreSame(token, tokentest); - Assert.AreSame(wrapper, wrappertest); - }); + await wrapper.SubmitAndGet(token); + await semaphore.WaitAsync(); + + + Assert.AreSame(token, tokentest); + Assert.AreSame(wrapper, wrappertest); } [Test] - [Timeout(100)] + [Timeout(500)] public void StopOnTimeout () { var wrapper = Injector.AsyncFrom( @@ -197,7 +195,7 @@ public void StopOnTimeout () StackWrapperSettings.With( runtime: RuntimeOptions.Default - .WhenNoMoreTasks(AsyncWaitingMethod.Timeout,1) + .WaitTimeout(10) ) ); From 9acfb511a5ec829b275dfc0e44b4b587317dbee0 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sat, 21 Aug 2021 04:30:24 +0200 Subject: [PATCH 16/17] clenup --- StackInjector/Core/AsyncStackWrapperCore.cs | 2 +- StackInjector/Core/AsyncStackWrapperCore.logic.cs | 1 - .../Core/InjectionCore/InjectionCore.reflection.cs | 2 +- .../Core/InjectionCore/InjectionCore.versioning.cs | 8 ++++---- StackInjector/Core/StackWrapperCore.cs | 3 +-- StackInjector/Settings/StackWrapperSettings.cs | 2 +- StackInjector/Settings/VersioningOptions.cs | 2 +- 7 files changed, 9 insertions(+), 11 deletions(-) diff --git a/StackInjector/Core/AsyncStackWrapperCore.cs b/StackInjector/Core/AsyncStackWrapperCore.cs index 5e6644f..22b3234 100644 --- a/StackInjector/Core/AsyncStackWrapperCore.cs +++ b/StackInjector/Core/AsyncStackWrapperCore.cs @@ -34,7 +34,7 @@ public CancellationToken PendingTasksCancellationToken // register an event that in case the list is empty, release the empty event listener. - internal AsyncStackWrapperCore ( InjectionCore core) : base(core) + internal AsyncStackWrapperCore ( InjectionCore core ) : base(core) { this.cancelPendingTasksSource.Token.Register(this.ReleaseListAwaiter); } diff --git a/StackInjector/Core/AsyncStackWrapperCore.logic.cs b/StackInjector/Core/AsyncStackWrapperCore.logic.cs index b62f92f..4b28e4a 100644 --- a/StackInjector/Core/AsyncStackWrapperCore.logic.cs +++ b/StackInjector/Core/AsyncStackWrapperCore.logic.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using StackInjector.Settings; namespace StackInjector.Core { diff --git a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs index bb2a567..4397185 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs @@ -28,7 +28,7 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr throw new ImplementationNotFoundException(type, $"can't find [Service] for interface {type.Name}"); else throw new ImplementationNotFoundException(type, $"can't find [Service] for {type.Name} v{servedAttribute.TargetVersion}"); - + } else { diff --git a/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs index bcaf55e..e85f1a6 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs @@ -14,15 +14,15 @@ internal partial class InjectionCore // performs versioning on the specified type private IEnumerable Version ( Type targetType, ServedAttribute servedAttribute ) { - if (targetType.IsSubclassOf( _istackwrappercore ) || targetType == _istackwrappercore) + if ( targetType.IsSubclassOf(_istackwrappercore) || targetType == _istackwrappercore ) return this.instances.TypesAssignableFrom(targetType); - if (this.settings.Versioning._customBindings != null && - this.settings.Versioning._customBindings.TryGetValue(targetType,out var t) ) + if ( this.settings.Versioning._customBindings != null && + this.settings.Versioning._customBindings.TryGetValue(targetType, out var t) ) { return Enumerable.Repeat(t, 1); } - + var targetVersion = servedAttribute?.TargetVersion ?? 0.0; var method = diff --git a/StackInjector/Core/StackWrapperCore.cs b/StackInjector/Core/StackWrapperCore.cs index 00b5b9f..b2b396c 100644 --- a/StackInjector/Core/StackWrapperCore.cs +++ b/StackInjector/Core/StackWrapperCore.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using StackInjector.Core.Cloning; using StackInjector.Settings; diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 20bc848..6db9efa 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -106,7 +106,7 @@ public static StackWrapperSettings With ( public static StackWrapperSettings DefaultBySubtraction { get - { + { var settings = Default; settings.Injection .ServingMethod(ServeAll, true); diff --git a/StackInjector/Settings/VersioningOptions.cs b/StackInjector/Settings/VersioningOptions.cs index 05c805b..7de19a8 100644 --- a/StackInjector/Settings/VersioningOptions.cs +++ b/StackInjector/Settings/VersioningOptions.cs @@ -21,7 +21,7 @@ public sealed class VersioningOptions : IOptions /// public HashSet AssemblyLookUpOrder { get; private set; } = new HashSet(); - + From c8bce9890f6ecd6f9e1cca5d366c6988b9a13231 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sun, 22 Aug 2021 03:48:09 +0200 Subject: [PATCH 17/17] Update Injector_Async.cs --- tests/StackInjector.TEST.BlackBox/Injector_Async.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/StackInjector.TEST.BlackBox/Injector_Async.cs b/tests/StackInjector.TEST.BlackBox/Injector_Async.cs index 33842be..313ac67 100644 --- a/tests/StackInjector.TEST.BlackBox/Injector_Async.cs +++ b/tests/StackInjector.TEST.BlackBox/Injector_Async.cs @@ -187,10 +187,10 @@ public async Task SubmitWithEvent () [Test] - [Timeout(500)] - public void StopOnTimeout () + [Timeout(1000)] + public async Task StopOnTimeout () { - var wrapper = Injector.AsyncFrom( + using var wrapper = Injector.AsyncFrom( (b,i,t) => b.ReturnArg(i,t), StackWrapperSettings.With( runtime: @@ -201,9 +201,12 @@ public void StopOnTimeout () Assume.That(!wrapper.IsElaborating); - wrapper.Elaborate().Wait(); + var elTask = wrapper.Elaborate(); + + await elTask; - Assert.That(!wrapper.IsElaborating && !wrapper.AnyTaskLeft()); + Assert.That(!wrapper.IsElaborating); + Assert.That(!wrapper.AnyTaskLeft()); }