From 338fcb3ef052f025128b245b0024371cb499326c Mon Sep 17 00:00:00 2001 From: Jacopo Date: Fri, 19 Feb 2021 13:00:47 +0100 Subject: [PATCH 01/26] divide StackWrapperSettings into submodules initial refactoring --- .../Core/AsyncStackWrapperCore.logic.cs | 4 +- StackInjector/Core/Cloning/ClonedCore.cs | 4 +- .../InjectionCore/InjectionCore.utilities.cs | 4 +- StackInjector/Core/StackWrapperCore.cs | 2 +- .../Core/injectionCore/InjectionCore.cs | 2 +- .../injectionCore/InjectionCore.injection.cs | 6 +- .../InjectionCore.instantiation.cs | 2 +- .../Core/injectionCore/InjectionCore.logic.cs | 6 +- .../injectionCore/InjectionCore.reflection.cs | 5 +- .../injectionCore/InjectionCore.versioning.cs | 4 +- .../StackWrapperSettings.configuration.cs | 205 ------------------ .../Settings/StackWrapperSettings.cs | 66 ++---- .../StackWrapperSettings.injection.cs | 121 +++++++++++ .../Settings/StackWrapperSettings.mask.cs | 119 ++++++++++ .../Settings/StackWrapperSettings.runtime.cs | 39 ++++ .../Features/Test.Versioning.cs | 8 +- .../UseCases/Exceptions.cs | 22 +- 17 files changed, 334 insertions(+), 285 deletions(-) delete mode 100644 StackInjector/Settings/StackWrapperSettings.configuration.cs create mode 100644 StackInjector/Settings/StackWrapperSettings.injection.cs create mode 100644 StackInjector/Settings/StackWrapperSettings.mask.cs create mode 100644 StackInjector/Settings/StackWrapperSettings.runtime.cs diff --git a/StackInjector/Core/AsyncStackWrapperCore.logic.cs b/StackInjector/Core/AsyncStackWrapperCore.logic.cs index 33cd2e8..96b2c84 100644 --- a/StackInjector/Core/AsyncStackWrapperCore.logic.cs +++ b/StackInjector/Core/AsyncStackWrapperCore.logic.cs @@ -85,7 +85,7 @@ Task listAwaiter () return this._emptyListAwaiter.WaitAsync(); } - switch( this.Settings._asyncWaitingMethod ) + switch( this.Settings.RuntimeOptions._asyncWaitingMethod ) { case AsyncWaitingMethod.Exit: @@ -103,7 +103,7 @@ Task listAwaiter () case AsyncWaitingMethod.Timeout: var list = listAwaiter(); - var timeout = Task.Delay( this.Settings._asyncWaitTime ); + var timeout = Task.Delay( this.Settings.RuntimeOptions._asyncWaitTime ); // if the timeout elapses first, then stop waiting return (await Task.WhenAny(list, timeout).ConfigureAwait(true)) == timeout; diff --git a/StackInjector/Core/Cloning/ClonedCore.cs b/StackInjector/Core/Cloning/ClonedCore.cs index e4c3eb7..6d9c792 100644 --- a/StackInjector/Core/Cloning/ClonedCore.cs +++ b/StackInjector/Core/Cloning/ClonedCore.cs @@ -20,7 +20,7 @@ public IAsyncStackWrapper ToAsyncWrapper ( }; this.clonedCore.EntryType = typeof(TEntry); - if( this.clonedCore.settings._registerAfterCloning ) + if( this.clonedCore.settings.Mask._registerAfterCloning ) this.clonedCore.ReadAssemblies(); this.clonedCore.ServeAll(cloned:true); @@ -32,7 +32,7 @@ public IStackWrapper ToWrapper () var wrapper = new StackWrapper(this.clonedCore); this.clonedCore.EntryType = typeof(T); - if( this.clonedCore.settings._registerAfterCloning ) + if( this.clonedCore.settings.Mask._registerAfterCloning ) this.clonedCore.ReadAssemblies(); this.clonedCore.ServeAll(cloned:true); diff --git a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs index d81413f..06c51b2 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs @@ -38,7 +38,7 @@ internal void RemoveUnusedTypes () // removes instances of the tracked instantiated types and call their Dispose method. Thread safe. protected internal void RemoveInstancesDiff () { - if( !this.settings._trackInstancesDiff ) + if( !this.settings.InjectionOptions._trackInstancesDiff ) return; // ensures that two threads are not trying to Dispose and InjectAll at the same time @@ -49,7 +49,7 @@ protected internal void RemoveInstancesDiff () this.instances[instance.GetType()].Remove(instance); // if the relative setting is true, check if the instance implements IDisposable and call it - if( this.settings._callDisposeOnInstanceDiff && instance is IDisposable disposable ) + if( this.settings.InjectionOptions._callDisposeOnInstanceDiff && instance is IDisposable disposable ) disposable.Dispose(); } diff --git a/StackInjector/Core/StackWrapperCore.cs b/StackInjector/Core/StackWrapperCore.cs index fd3d3ba..a4792e0 100644 --- a/StackInjector/Core/StackWrapperCore.cs +++ b/StackInjector/Core/StackWrapperCore.cs @@ -23,7 +23,7 @@ public StackWrapperCore ( InjectionCore core, Type toRegister ) this.Core = core; // setting for referencing the calling wrapper as a service - if( this.Core.settings._registerWrapperAsService ) + if( this.Core.settings.MaskOptions._registerWrapperAsService ) { this.Core.instances.AddType(toRegister); this.Core.instances[toRegister].Clear(); diff --git a/StackInjector/Core/injectionCore/InjectionCore.cs b/StackInjector/Core/injectionCore/InjectionCore.cs index 2a3962f..e37189a 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.cs @@ -53,7 +53,7 @@ internal InjectionCore ( StackWrapperSettings settings ) this.instances = new InstancesHolder(); - if( this.settings._trackInstancesDiff ) + if( this.settings.InjectionOptions._trackInstancesDiff ) this.instancesDiff = new List(); } diff --git a/StackInjector/Core/injectionCore/InjectionCore.injection.cs b/StackInjector/Core/injectionCore/InjectionCore.injection.cs index d5d8281..631f8cf 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.injection.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.injection.cs @@ -23,8 +23,8 @@ private IEnumerable InjectServicesInto ( object instance ) // otherwise check if the type has a service attribute and // if its property has been defined. var serving = - (this.settings._overrideServingMethod || serviceAtt is null || !(serviceAtt._servingDefined)) - ? this.settings._servingMethod + (this.settings.InjectionOptions._overrideServingMethod || serviceAtt is null || !(serviceAtt._servingDefined)) + ? this.settings.InjectionOptions._servingMethod : serviceAtt.Serving; // don't waste time serving if not necessary @@ -105,7 +105,7 @@ ref used private object InstTypeOrServiceEnum ( Type type, ServedAttribute servedAttribute, ref List used ) { if ( - this.settings._serveEnumerables + this.settings.InjectionOptions._serveEnumerables && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>) ) diff --git a/StackInjector/Core/injectionCore/InjectionCore.instantiation.cs b/StackInjector/Core/injectionCore/InjectionCore.instantiation.cs index 784eba8..f750631 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.instantiation.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.instantiation.cs @@ -25,7 +25,7 @@ private object InstantiateService ( Type type ) this.instances.total_count++; // if true, track instantiated objects - if( this.settings._trackInstancesDiff ) + if( this.settings.InjectionOptions._trackInstancesDiff ) this.instancesDiff.Add(instance); return instance; diff --git a/StackInjector/Core/injectionCore/InjectionCore.logic.cs b/StackInjector/Core/injectionCore/InjectionCore.logic.cs index f14489a..0bc4ed0 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.logic.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.logic.cs @@ -51,16 +51,16 @@ internal void ServeAll ( bool cloned = false ) } // cleanup - if( this.settings._cleanUnusedTypesAftInj ) + if( this.settings.InjectionOptions._cleanUnusedTypesAftInj ) this.RemoveUnusedTypes(); void checkInstancesLimit () { - if ( this.instances.total_count > this.settings._limitInstancesCount ) + if ( this.instances.total_count > this.settings.InjectionOptions._limitInstancesCount ) throw new InstancesLimitReachedException( - $"Reached limit of {this.settings._limitInstancesCount} instances." + $"Reached limit of {this.settings.InjectionOptions._limitInstancesCount} instances." ); } } diff --git a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs b/StackInjector/Core/injectionCore/InjectionCore.reflection.cs index 9550dbf..c40b2e2 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.reflection.cs @@ -38,13 +38,14 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr // reads all [Service] classes internal void ReadAssemblies () { - if( this.settings._registerEntryPointAssembly ) - this.settings._registredAssemblies.Add(this.EntryType.Assembly); + if( this.settings.Mask._registerEntryPointAssembly ) + this.settings.Mask._registredAssemblies.Add(this.EntryType.Assembly); foreach ( var t in this .settings + .Mask ._registredAssemblies .SelectMany ( diff --git a/StackInjector/Core/injectionCore/InjectionCore.versioning.cs b/StackInjector/Core/injectionCore/InjectionCore.versioning.cs index 9a2b9b4..d2a31e9 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.versioning.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.versioning.cs @@ -15,8 +15,8 @@ private IEnumerable Version ( Type targetType, ServedAttribute servedAttri var targetVersion = servedAttribute?.TargetVersion ?? 0.0; var method = - (this.settings._overrideTargetingMethod || servedAttribute is null || !(servedAttribute._targetingDefined)) - ? this.settings._targetingMethod + (this.settings.InjectionOptions._overrideTargetingMethod || servedAttribute is null || !(servedAttribute._targetingDefined)) + ? this.settings.InjectionOptions._targetingMethod : servedAttribute.TargetingMethod; var candidateTypes = this.instances.TypesAssignableFrom(targetType); diff --git a/StackInjector/Settings/StackWrapperSettings.configuration.cs b/StackInjector/Settings/StackWrapperSettings.configuration.cs deleted file mode 100644 index 60dd732..0000000 --- a/StackInjector/Settings/StackWrapperSettings.configuration.cs +++ /dev/null @@ -1,205 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text.RegularExpressions; - -namespace StackInjector.Settings -{ - public sealed partial class StackWrapperSettings - { - - #region registration - - /// - /// Register an external assembly from wich you want classes to be laoded. - /// - /// - /// the modified settings - public StackWrapperSettings RegisterAssemblies ( params Assembly[] assemblies ) - { - if( assemblies is null ) - throw new ArgumentNullException(nameof(assemblies)); - - foreach( var assembly in assemblies ) - this._registredAssemblies.Add(assembly); - return this; - } - - /// - /// Automatically register all domain assemblies, filtering the specified ones.
- /// Warning: CPU expensive - ///
- /// a regex string used to filter unwanted matching assemblies - /// the modified settings - public StackWrapperSettings RegisterDomain ( string regexFilter = Injector.Defaults.AssemblyRegexFilter ) - { - this.RegisterAssemblies - ( - AppDomain.CurrentDomain - .GetAssemblies() - .Where(a => !Regex.IsMatch(a.FullName, regexFilter)) - .ToArray() - ); - - return this; - } - - /// - /// Register the assembly of the specified type. - /// Same as . - /// - /// - /// the modified settings - public StackWrapperSettings RegisterAssemblyOf () - { - this.RegisterAssemblies(typeof(T).Assembly); - return this; - } - - /// - /// Register the entry point assembly when starting. - /// If set, there is no need to specify the entry assembly in . - /// Default is true. - /// - /// the modified settings - public StackWrapperSettings RegisterEntryAssembly ( bool register = true ) - { - this._registerEntryPointAssembly = register; - return this; - } - - /// - /// Register the wrapper as a service, so it can be accessed in contained classes. - /// Default is true. - /// - /// the modified settings - public StackWrapperSettings RegisterWrapperAsService ( bool register = true ) - { - this._registerWrapperAsService = register; - return this; - } - - - /// - /// If set, when cloned the StackWrapper will re-scans all assemblies before the injection. - /// Used to update assemblies with new types. - /// - /// the modified settings - public StackWrapperSettings RegisterAfterCloning ( bool register = true ) - { - this._registerAfterCloning = register; - return this; - } - - #endregion - - - #region disposing - - /// - /// Track every new instantiated class to be deleted upon Dispose. - /// - /// if true, track instances diff - /// if true, call Dispose on services implementing - /// the modified settings - public StackWrapperSettings TrackInstantiationDiff ( bool track = true, bool callDispose = true ) - { - this._trackInstancesDiff = track; - this._callDisposeOnInstanceDiff = callDispose; - return this; - } - - #endregion - - #region async - - /// - /// 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 - /// the modified settings - public StackWrapperSettings WhenNoMoreTasks ( AsyncWaitingMethod waitingMethod, int waitTime = 1000 ) - { - this._asyncWaitingMethod = waitingMethod; - this._asyncWaitTime = waitTime; - return this; - } - - #endregion - - - #region injection - - /// - /// Overrides default targetting method - /// - /// the new default targetting method - /// if true, versioning methods for [Served] fields and properties are overriden - /// the modified settings - public StackWrapperSettings InjectionVersioningMethod ( ServedVersionTargetingMethod targetMethod, bool @override = false ) - { - this._targetingMethod = targetMethod; - this._overrideTargetingMethod = @override; - return this; - } - - /// - /// Overrides default serving method - /// - /// the new default serving method for all services - /// if true, serving methods for [Service] calsses are overridden with the specified one - /// the modified settings - public StackWrapperSettings InjectionServingMethods ( ServingMethods methods, bool @override = false ) - { - this._servingMethod = methods; - this._overrideServingMethod = @override; - return this; - } - - - /// - /// Remove the reference to unused types after the injection is finished. - /// - /// The modified settings - public StackWrapperSettings RemoveUnusedTypesAfterInjection ( bool remove = true ) - { - this._cleanUnusedTypesAftInj = remove; - return this; - } - - /// - /// Limits the TOTAL number of instances.
- /// You can use to remove this limit, altough it is suggest to use the lowest possible value. - ///
- /// the limit of total instances - /// The modified settings - public StackWrapperSettings LimitInstancesCount ( uint count = 128 ) - { - this._limitInstancesCount = count; - return this; - } - - #endregion - - - - #region features - - /// - /// Allows to be injected with a list of every service implementing T - /// - /// if true, serve - /// the modified settings - public StackWrapperSettings ServeIEnumerables ( bool serve = true ) - { - this._serveEnumerables = serve; - return this; - } - - #endregion - - } -} diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 500d495..7988ad8 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -9,40 +9,12 @@ namespace StackInjector.Settings /// /// Used to manage the behaviour of and /// - [Serializable] public sealed partial class StackWrapperSettings { - // list of settings and their initial empty definition - #region settings - - // registration - internal HashSet _registredAssemblies = new HashSet(); - internal bool _registerEntryPointAssembly; - internal bool _registerWrapperAsService; - internal bool _registerAfterCloning; - - // disposing - internal bool _trackInstancesDiff; - internal bool _callDisposeOnInstanceDiff; - - // async management - internal AsyncWaitingMethod _asyncWaitingMethod = AsyncWaitingMethod.Exit; - internal int _asyncWaitTime = 500; - - // injection - internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; - internal bool _overrideTargetingMethod; - - internal ServingMethods _servingMethod = ServingMethods.DoNotServe; - internal bool _overrideServingMethod; - internal bool _cleanUnusedTypesAftInj; - internal uint _limitInstancesCount = 128; - - // features - internal bool _serveEnumerables; - - #endregion + public Mask MaskOptions { get; private set; } + public Injection InjectionOptions { get; private set; } + public Runtime RuntimeOptions { get; private set; } private StackWrapperSettings () { } @@ -56,7 +28,7 @@ public StackWrapperSettings Copy () { var settingsCopy = (StackWrapperSettings)this.MemberwiseClone(); // creats a deep copy of reference objects - settingsCopy._registredAssemblies = this._registredAssemblies.ToHashSet(); + settingsCopy.MaskOptions._registredAssemblies = this.MaskOptions._registredAssemblies.ToHashSet(); return settingsCopy; } @@ -72,21 +44,15 @@ public static StackWrapperSettings Empty new StackWrapperSettings(); - /// - /// Creates a new StackWrapperSettings with default parameters. - /// - /// the default settings - public static StackWrapperSettings Default - => - new StackWrapperSettings() - .RegisterEntryAssembly() - .RegisterWrapperAsService() - .RegisterAfterCloning(false) - .TrackInstantiationDiff(false, callDispose: false) - .InjectionVersioningMethod(ServedVersionTargetingMethod.None, @override: false) - .InjectionServingMethods(Injector.Defaults.ServeAllStrict, @override: false) - .WhenNoMoreTasks(AsyncWaitingMethod.Exit) - .ServeIEnumerables(); + + public static StackWrapperSettings Default ( Injection injection = null, Runtime runtime = null, Mask mask = null ) + => + new StackWrapperSettings() + { + MaskOptions = mask ?? Mask.Default, + InjectionOptions = injection ?? Injection.Default, + RuntimeOptions = runtime ?? Runtime.Default + }; /// @@ -95,8 +61,8 @@ public static StackWrapperSettings Default /// /// public static StackWrapperSettings DefaultBySubtraction - => - Default - .InjectionServingMethods(Injector.Defaults.ServeAll, @override: true); + => Default(Injection.Default.InjectionServingMethods(Injector.Defaults.ServeAll, true)); + + } } \ No newline at end of file diff --git a/StackInjector/Settings/StackWrapperSettings.injection.cs b/StackInjector/Settings/StackWrapperSettings.injection.cs new file mode 100644 index 0000000..abdfedd --- /dev/null +++ b/StackInjector/Settings/StackWrapperSettings.injection.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StackInjector.Settings +{ + partial class StackWrapperSettings + { + + public sealed class Injection + { + internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; + internal bool _overrideTargetingMethod; + + internal ServingMethods _servingMethod = ServingMethods.DoNotServe; + internal bool _overrideServingMethod; + internal bool _cleanUnusedTypesAftInj; + internal uint _limitInstancesCount = 128; + + internal bool _serveEnumerables; + + // disposing + internal bool _trackInstancesDiff; + internal bool _callDisposeOnInstanceDiff; + + + internal Injection () { } + + public static Injection Default => + new Injection() + .TrackInstantiationDiff(false, false) + .InjectionVersioningMethod(ServedVersionTargetingMethod.None, false) + .InjectionServingMethods(Injector.Defaults.ServeAllStrict, false) + .ServeIEnumerables(); + + + #region configuration methods + + + /// + /// Track every new instantiated class to be deleted upon Dispose. + /// + /// if true, track instances diff + /// if true, call Dispose on services implementing + /// the modified settings + public Injection TrackInstantiationDiff ( bool track = true, bool callDispose = true ) + { + this._trackInstancesDiff = track; + this._callDisposeOnInstanceDiff = callDispose; + 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 Injection InjectionVersioningMethod ( ServedVersionTargetingMethod targetMethod, bool @override = false ) + { + this._targetingMethod = targetMethod; + this._overrideTargetingMethod = @override; + return this; + } + + /// + /// Overrides default serving method + /// + /// the new default serving method for all services + /// if true, serving methods for [Service] calsses are overridden with the specified one + /// the modified settings + public Injection InjectionServingMethods ( ServingMethods methods, bool @override = false ) + { + this._servingMethod = methods; + this._overrideServingMethod = @override; + return this; + } + + + /// + /// Remove the reference to unused types after the injection is finished. + /// + /// The modified settings + public Injection RemoveUnusedTypesAfterInjection ( bool remove = true ) + { + this._cleanUnusedTypesAftInj = remove; + return this; + } + + /// + /// Limits the TOTAL number of instances.
+ /// You can use to remove this limit, altough it is suggest to use the lowest possible value. + ///
+ /// the limit of total instances + /// The modified settings + public Injection LimitInstancesCount ( uint count = 128 ) + { + this._limitInstancesCount = count; + return this; + } + + /// + /// Allows to be injected with a list of every service implementing T + /// + /// if true, serve + /// the modified settings + public Injection ServeIEnumerables ( bool serve = true ) + { + this._serveEnumerables = serve; + return this; + } + + + #endregion + + + } + + } +} diff --git a/StackInjector/Settings/StackWrapperSettings.mask.cs b/StackInjector/Settings/StackWrapperSettings.mask.cs new file mode 100644 index 0000000..fe98a36 --- /dev/null +++ b/StackInjector/Settings/StackWrapperSettings.mask.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; + +namespace StackInjector.Settings +{ + partial class StackWrapperSettings + { + + public sealed class Mask + { + // registration + internal HashSet _registredAssemblies = new HashSet(); + internal bool _registerEntryPointAssembly; + internal bool _registerWrapperAsService; + internal bool _registerAfterCloning; + + public static Mask Default => + new Mask() + { + _registerEntryPointAssembly = true, + _registerWrapperAsService = true, + _registerAfterCloning = false + }; + //.RegisterEntryAssembly() + //.RegisterWrapperAsService() + //.RegisterAfterCloning(false); + + internal Mask () { } + + + /// + /// Register an external assembly from wich you want classes to be laoded. + /// + /// + /// the modified settings + public Mask RegisterAssemblies ( params Assembly[] assemblies ) + { + if ( assemblies is null ) + throw new ArgumentNullException(nameof(assemblies)); + + foreach ( var assembly in assemblies ) + this._registredAssemblies.Add(assembly); + return this; + } + + /// + /// Automatically register all domain assemblies, filtering the specified ones.
+ /// Warning: CPU expensive + ///
+ /// a regex string used to filter unwanted matching assemblies + /// the modified settings + public Mask RegisterDomain ( string regexFilter = Injector.Defaults.AssemblyRegexFilter ) + { + this.RegisterAssemblies + ( + AppDomain.CurrentDomain + .GetAssemblies() + .Where(a => !Regex.IsMatch(a.FullName, regexFilter)) + .ToArray() + ); + + return this; + } + + /// + /// Register the assembly of the specified type. + /// Same as . + /// + /// + /// the modified settings + public Mask RegisterAssemblyOf () + { + this.RegisterAssemblies(typeof(T).Assembly); + return this; + } + + /// + /// Register the entry point assembly when starting. + /// If set, there is no need to specify the entry assembly in . + /// Default is true. + /// + /// the modified settings + public Mask RegisterEntryAssembly ( bool register = true ) + { + this._registerEntryPointAssembly = register; + return this; + } + + /// + /// Register the wrapper as a service, so it can be accessed in contained classes. + /// Default is true. + /// + /// the modified settings + public Mask RegisterWrapperAsService ( bool register = true ) + { + this._registerWrapperAsService = register; + return this; + } + + + /// + /// If set, when cloned the StackWrapper will re-scans all assemblies before the injection. + /// Used to update assemblies with new types. + /// + /// the modified settings + public Mask RegisterAfterCloning ( bool register = true ) + { + this._registerAfterCloning = register; + return this; + } + + } + + } +} diff --git a/StackInjector/Settings/StackWrapperSettings.runtime.cs b/StackInjector/Settings/StackWrapperSettings.runtime.cs new file mode 100644 index 0000000..814f8fa --- /dev/null +++ b/StackInjector/Settings/StackWrapperSettings.runtime.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StackInjector.Settings +{ + partial class StackWrapperSettings + { + public sealed class Runtime + { + + // async management + internal AsyncWaitingMethod _asyncWaitingMethod = AsyncWaitingMethod.Exit; + internal int _asyncWaitTime = 500; + + + internal Runtime () { } + + public static Runtime Default => + new Runtime() + .WhenNoMoreTasks(AsyncWaitingMethod.Exit); + + + /// + /// 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 + /// the modified settings + public Runtime WhenNoMoreTasks ( AsyncWaitingMethod waitingMethod, int waitTime = 1000 ) + { + this._asyncWaitingMethod = waitingMethod; + this._asyncWaitTime = waitTime; + return this; + } + } + } +} diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs index 4bd43c0..05c00ce 100644 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs +++ b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs @@ -13,8 +13,8 @@ internal class Versioning : CommonTestingMethods [Test] public void ServedVersioningClass () { - var settings = - StackWrapperSettings.Default + var settings = StackWrapperSettings.Default(); + settings.InjectionOptions .InjectionVersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); var versionedService = Injector.From(settings).Entry.Level1_2; @@ -38,8 +38,8 @@ public void ServedVersioningInterface () [Test] public void SettingVersioningLatestMaj () { - var settings = - StackWrapperSettings.Default + var settings = StackWrapperSettings.Default(); + settings.InjectionOptions .InjectionVersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); var versionedService = Injector.From( settings ).Entry.level1; diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index cc6ae6e..203a1d9 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -10,6 +10,8 @@ using StackInjector.TEST.ExternalAssembly; using StackInjector.TEST; +using SWS = StackInjector.Settings.StackWrapperSettings; + namespace StackInjector.TEST.BlackBox.UseCases { @@ -48,9 +50,12 @@ public void ThrowsServiceNotFound () [Test] public void ExternalAssemblyReference () { - var settings = - StackWrapperSettings.Default - .RegisterAssemblyOf(); + var settings = SWS.Default( + mask: + SWS.Mask.Default + .RegisterAssemblyOf() + ); + var externalClass = Injector.From(settings).Entry.externalClass; @@ -62,7 +67,7 @@ public void ExternalAssemblyReference () public void ExternalAllAssemblyReference () { var settings = - StackWrapperSettings.Default + SWS.Default .RegisterDomain(); @@ -137,7 +142,8 @@ private class SingletonLoopInjectionNotThrower { [Served] readonly SingletonLoop [Timeout(500)] public void NotThrowsInstLimitReach_Singleton_wBase () { - var settings = StackWrapperSettings.Default + var settings = SWS.Default(); + settings.InjectionOptions .LimitInstancesCount(2); Assert.DoesNotThrow(() => Injector.From(settings)); } @@ -147,7 +153,8 @@ public void NotThrowsInstLimitReach_Singleton_wBase () [Timeout(500)] public void NotThrowsInstLimitReach_Singleton () { - var settings = StackWrapperSettings.Default + var settings = SWS.Default(); + settings.InjectionOptions .LimitInstancesCount(2); Assert.DoesNotThrow(() => Injector.From(settings)); } @@ -159,7 +166,8 @@ public void NotThrowsInstLimitReach_Singleton () [Timeout(500)] public void ThrowsInstLimitReach_Cloned () { - var settings = StackWrapperSettings.Default + var settings = SWS.Default(); + settings.InjectionOptions .LimitInstancesCount(1); Assert.Throws( () => Injector.From().CloneCore(settings).ToWrapper() ); } From 3130ead5d3e453854cf8139f31fa8cbfc0f380c2 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sat, 20 Feb 2021 08:07:39 +0100 Subject: [PATCH 02/26] refactored tests --- StackInjector/Core/Cloning/ClonedCore.cs | 4 ++-- .../injectionCore/InjectionCore.reflection.cs | 6 +++--- StackInjector/Injector.cs | 4 ++-- .../Settings/StackWrapperSettings.injection.cs | 14 +++++++------- .../Settings/StackWrapperSettings.mask.cs | 15 +++------------ .../Settings/StackWrapperSettings.runtime.cs | 4 +--- .../Features/Test.InstantiationDiff.cs | 12 ++++++++---- .../Features/Test.Versioning.cs | 4 ++-- .../UseCases/Exceptions.cs | 5 ++--- .../StackInjector.TEST.BlackBox/UseCases/Sync.cs | 15 ++++++++------- 10 files changed, 38 insertions(+), 45 deletions(-) diff --git a/StackInjector/Core/Cloning/ClonedCore.cs b/StackInjector/Core/Cloning/ClonedCore.cs index 6d9c792..59bc858 100644 --- a/StackInjector/Core/Cloning/ClonedCore.cs +++ b/StackInjector/Core/Cloning/ClonedCore.cs @@ -20,7 +20,7 @@ public IAsyncStackWrapper ToAsyncWrapper ( }; this.clonedCore.EntryType = typeof(TEntry); - if( this.clonedCore.settings.Mask._registerAfterCloning ) + if( this.clonedCore.settings.MaskOptions._registerAfterCloning ) this.clonedCore.ReadAssemblies(); this.clonedCore.ServeAll(cloned:true); @@ -32,7 +32,7 @@ public IStackWrapper ToWrapper () var wrapper = new StackWrapper(this.clonedCore); this.clonedCore.EntryType = typeof(T); - if( this.clonedCore.settings.Mask._registerAfterCloning ) + if( this.clonedCore.settings.MaskOptions._registerAfterCloning ) this.clonedCore.ReadAssemblies(); this.clonedCore.ServeAll(cloned:true); diff --git a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs b/StackInjector/Core/injectionCore/InjectionCore.reflection.cs index c40b2e2..41fb31c 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.reflection.cs @@ -38,14 +38,14 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr // reads all [Service] classes internal void ReadAssemblies () { - if( this.settings.Mask._registerEntryPointAssembly ) - this.settings.Mask._registredAssemblies.Add(this.EntryType.Assembly); + if( this.settings.MaskOptions._registerEntryPointAssembly ) + this.settings.MaskOptions._registredAssemblies.Add(this.EntryType.Assembly); foreach ( var t in this .settings - .Mask + .MaskOptions ._registredAssemblies .SelectMany ( diff --git a/StackInjector/Injector.cs b/StackInjector/Injector.cs index 1c92664..31a2c57 100644 --- a/StackInjector/Injector.cs +++ b/StackInjector/Injector.cs @@ -29,7 +29,7 @@ public static partial class Injector public static IStackWrapper From ( StackWrapperSettings settings = null ) { if( settings == null ) - settings = StackWrapperSettings.Default; + settings = StackWrapperSettings.Default(); // create the core and wrap it var core = new InjectionCore( settings ) @@ -72,7 +72,7 @@ public static IAsyncStackWrapper AsyncFrom ) { if( settings == null ) - settings = StackWrapperSettings.Default; + settings = StackWrapperSettings.Default(); // create the core and wrap it var core = new InjectionCore( settings ) diff --git a/StackInjector/Settings/StackWrapperSettings.injection.cs b/StackInjector/Settings/StackWrapperSettings.injection.cs index abdfedd..d00e62d 100644 --- a/StackInjector/Settings/StackWrapperSettings.injection.cs +++ b/StackInjector/Settings/StackWrapperSettings.injection.cs @@ -12,12 +12,12 @@ public sealed class Injection internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; internal bool _overrideTargetingMethod; - internal ServingMethods _servingMethod = ServingMethods.DoNotServe; + internal ServingMethods _servingMethod = Injector.Defaults.ServeAllStrict; internal bool _overrideServingMethod; internal bool _cleanUnusedTypesAftInj; internal uint _limitInstancesCount = 128; - internal bool _serveEnumerables; + internal bool _serveEnumerables = true; // disposing internal bool _trackInstancesDiff; @@ -27,11 +27,11 @@ public sealed class Injection internal Injection () { } public static Injection Default => - new Injection() - .TrackInstantiationDiff(false, false) - .InjectionVersioningMethod(ServedVersionTargetingMethod.None, false) - .InjectionServingMethods(Injector.Defaults.ServeAllStrict, false) - .ServeIEnumerables(); + new Injection(); + //.TrackInstantiationDiff(false, false) + //.InjectionVersioningMethod(ServedVersionTargetingMethod.None, false) + //.InjectionServingMethods(Injector.Defaults.ServeAllStrict, false) + //.ServeIEnumerables(); #region configuration methods diff --git a/StackInjector/Settings/StackWrapperSettings.mask.cs b/StackInjector/Settings/StackWrapperSettings.mask.cs index fe98a36..7b25ebe 100644 --- a/StackInjector/Settings/StackWrapperSettings.mask.cs +++ b/StackInjector/Settings/StackWrapperSettings.mask.cs @@ -14,20 +14,11 @@ public sealed class Mask { // registration internal HashSet _registredAssemblies = new HashSet(); - internal bool _registerEntryPointAssembly; - internal bool _registerWrapperAsService; + internal bool _registerEntryPointAssembly = true; + internal bool _registerWrapperAsService = true; internal bool _registerAfterCloning; - public static Mask Default => - new Mask() - { - _registerEntryPointAssembly = true, - _registerWrapperAsService = true, - _registerAfterCloning = false - }; - //.RegisterEntryAssembly() - //.RegisterWrapperAsService() - //.RegisterAfterCloning(false); + public static Mask Default => new Mask(); internal Mask () { } diff --git a/StackInjector/Settings/StackWrapperSettings.runtime.cs b/StackInjector/Settings/StackWrapperSettings.runtime.cs index 814f8fa..a6efd25 100644 --- a/StackInjector/Settings/StackWrapperSettings.runtime.cs +++ b/StackInjector/Settings/StackWrapperSettings.runtime.cs @@ -16,9 +16,7 @@ public sealed class Runtime internal Runtime () { } - public static Runtime Default => - new Runtime() - .WhenNoMoreTasks(AsyncWaitingMethod.Exit); + public static Runtime Default => new Runtime(); /// diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs index 6e088e5..e65a697 100644 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs +++ b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs @@ -31,7 +31,8 @@ private class ServiceA [Test] public void SimpleClone () { - var settings = StackWrapperSettings.Default + var settings = StackWrapperSettings.Default(); + settings.InjectionOptions .TrackInstantiationDiff(); IStackWrapper wrapperB; @@ -56,7 +57,8 @@ public void SimpleClone () [Test] public void SimpleCloneWithDispose () { - var settings = StackWrapperSettings.Default + var settings = StackWrapperSettings.Default(); + settings.InjectionOptions .TrackInstantiationDiff(); IStackWrapper wrapperB; @@ -76,7 +78,8 @@ public void SimpleCloneWithDispose () [Test] public void DeepClone () { - var settings = StackWrapperSettings.Default + var settings = StackWrapperSettings.Default(); + settings.InjectionOptions .TrackInstantiationDiff(); IStackWrapper wrapperB; @@ -100,7 +103,8 @@ public void DeepClone () [Test] public void DeepCloneWithDispose () { - var settings = StackWrapperSettings.Default + var settings = StackWrapperSettings.Default(); + settings.InjectionOptions .TrackInstantiationDiff(); IStackWrapper wrapperB; diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs index 05c00ce..020ea9a 100644 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs +++ b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs @@ -51,8 +51,8 @@ public void SettingVersioningLatestMaj () [Test] public void SettingVersioningLatestMin () { - var settings = - StackWrapperSettings.Default + var settings = StackWrapperSettings.Default(); + settings.InjectionOptions .InjectionVersioningMethod(ServedVersionTargetingMethod.LatestMinor,true); var versionedService = Injector.From( settings ).Entry.level1; diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index 203a1d9..502b93e 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -66,9 +66,8 @@ public void ExternalAssemblyReference () [Test] public void ExternalAllAssemblyReference () { - var settings = - SWS.Default - .RegisterDomain(); + var settings = SWS.Default(); + settings.MaskOptions.RegisterDomain(); var externalClass = Injector.From(settings).Entry.externalClass; diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs index e08c1ee..89466b1 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs @@ -44,8 +44,8 @@ public void FromInterface () [Test] public void ServeStrict () { - var settings = - StackWrapperSettings.Default + var settings = StackWrapperSettings.Default(); + settings.InjectionOptions .InjectionServingMethods( Injector.Defaults.ServeAllStrict, true ); var entry = Injector.From(settings).Entry; @@ -58,7 +58,8 @@ public void ServeStrict () public void RemoveUnusedTypes () { var settings = - StackWrapperSettings.Default + StackWrapperSettings.Default(); + settings.InjectionOptions .RemoveUnusedTypesAfterInjection(); var wrap1 = Injector.From( settings ); @@ -128,10 +129,10 @@ public void RegisterAfterCloning () // BaseServiceNotFoundThrower uses a class in an external assembly Assert.Throws(() => wrapper1.CloneCore().ToWrapper()); - var settings = - StackWrapperSettings.Default - .RegisterAssemblyOf() - .RegisterAfterCloning(); + var settings = StackWrapperSettings.Default(); + settings.MaskOptions + .RegisterAssemblyOf() + .RegisterAfterCloning(); Assert.DoesNotThrow(() => wrapper1.CloneCore(settings).ToWrapper()); From cb817698bd41af4dbc8e22a5f93cb7a7bbda34fb Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sat, 20 Feb 2021 08:32:14 +0100 Subject: [PATCH 03/26] fixed Retry-Timeout tests --- .../CommonTestingMethods.cs | 17 ++++++++++ .../UseCases/Async.cs | 21 ++++++------ .../UseCases/Exceptions.cs | 32 +++++++++++-------- 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs b/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs index 842fa55..16abf93 100644 --- a/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs +++ b/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs @@ -13,6 +13,23 @@ namespace StackInjector.TEST.BlackBox /// class CommonTestingMethods { + // this is done because apaprently [Timeout] and [Retry] together just don't work + protected static void ExecuteTest ( int timeout, Action test ) + { + try + { + var task = Task.Run(test); + if ( !task.Wait(timeout)) + throw new TimeoutException("Timed out"); + } + catch ( Exception ex ) + { + //If the caught exception is not an assert exception but an unhandled exception. + if ( !(ex is AssertionException) ) + Assert.Fail(ex.Message); + } + } + #if RELEASE [TearDown] public void ConsoleLogOnError () diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs index 3ddfdac..375938e 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs @@ -102,20 +102,23 @@ public async Task SubmitAndCatchAsyncEnumerable () [Test] [Retry(3)] - [Timeout(1000)] + //[Timeout(1000)] public void TaskCancellation () { - var wrapper = Injector.AsyncFrom( (b,i,t) => b.WaitForever(i,t) ); - var task = wrapper.SubmitAndGet(new object()); + ExecuteTest(1000, () => + { + var wrapper = Injector.AsyncFrom( (b,i,t) => b.WaitForever(i,t) ); + var task = wrapper.SubmitAndGet(new object()); - var elaborationTask = wrapper.Elaborate(); + var elaborationTask = wrapper.Elaborate(); - wrapper.Dispose(); + wrapper.Dispose(); - Assert.Multiple(() => - { - var aggregate = Assert.Throws(()=>task.Wait()); - Assert.IsInstanceOf(aggregate.InnerException); + Assert.Multiple(() => + { + var aggregate = Assert.Throws(()=>task.Wait()); + Assert.IsInstanceOf(aggregate.InnerException); + }); }); } diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index 502b93e..f5af517 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -11,6 +11,7 @@ using StackInjector.TEST; using SWS = StackInjector.Settings.StackWrapperSettings; +using System.Threading.Tasks; namespace StackInjector.TEST.BlackBox.UseCases { @@ -120,7 +121,7 @@ private class AlwaysCreateLoopInjectionThrower {[Served] private readonly Always private class InstantiationPatternBase {[Served] private readonly AlwaysCreateLoopInjectionThrower loop; } [Test] - [Timeout(500)] + [Timeout(200)] public void ThrowsInstLimitReach_AlwaysCreate () { Assert.Throws(() => Injector.From()); @@ -137,25 +138,30 @@ private class SingletonLoopInjectionNotThrowerBase { [Served] readonly Singleton private class SingletonLoopInjectionNotThrower { [Served] readonly SingletonLoopInjectionNotThrower self; } - [Test] - [Timeout(500)] + [Test][Retry(3)] + //[Timeout(200)] public void NotThrowsInstLimitReach_Singleton_wBase () { - var settings = SWS.Default(); - settings.InjectionOptions - .LimitInstancesCount(2); - Assert.DoesNotThrow(() => Injector.From(settings)); + ExecuteTest(100, () => + { + var settings = SWS.Default(); + settings.InjectionOptions + .LimitInstancesCount(2); + Assert.DoesNotThrow(() => Injector.From(settings)); + }); } - [Test] - [Timeout(500)] + [Test][Retry(3)] + //[Timeout(200)] public void NotThrowsInstLimitReach_Singleton () { - var settings = SWS.Default(); - settings.InjectionOptions - .LimitInstancesCount(2); - Assert.DoesNotThrow(() => Injector.From(settings)); + ExecuteTest(100, () => + { + var settings = SWS.Default(); + settings.InjectionOptions.LimitInstancesCount(2); + Assert.DoesNotThrow(() => Injector.From(settings)); + }); } // ---------- From 70f34b8bb9d2f1a25d678c6a21630d5d65c50cbf Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sat, 20 Feb 2021 08:43:33 +0100 Subject: [PATCH 04/26] Update CommonTestingMethods.cs --- .../CommonTestingMethods.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs b/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs index 16abf93..b590162 100644 --- a/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs +++ b/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs @@ -30,18 +30,18 @@ protected static void ExecuteTest ( int timeout, Action test ) } } -#if RELEASE - [TearDown] - public void ConsoleLogOnError () - { - var result = TestContext.CurrentContext.Result.Outcome.Status; - if ( result == TestStatus.Failed || result == TestStatus.Inconclusive ) - { - Console.WriteLine( - $"\t\tFailed:{TestContext.CurrentContext.Test.FullName}\n\t\tMessage:{TestContext.CurrentContext.Result.Message}" - ); - } - } -#endif +////#if RELEASE +//// [TearDown] +//// public void ConsoleLogOnError () +//// { +//// var result = TestContext.CurrentContext.Result.Outcome.Status; +//// if ( result == TestStatus.Failed || result == TestStatus.Inconclusive ) +//// { +//// Console.WriteLine( +//// $"\t\tFailed:{TestContext.CurrentContext.Test.FullName}\n\t\tMessage:{TestContext.CurrentContext.Result.Message}" +//// ); +//// } +//// } +////#endif } } From cfb146be894c7dfbf0659163a469517b36d8d875 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sun, 21 Feb 2021 12:45:07 +0100 Subject: [PATCH 05/26] remove types registration. no internal logic change all tests should fail. --- StackInjector/Core/Cloning/ClonedCore.cs | 10 +- StackInjector/Core/StackWrapperCore.cs | 17 +-- .../injectionCore/InjectionCore.reflection.cs | 48 ++++---- StackInjector/Injector.cs | 8 +- .../DefaultConstants.cs} | 6 +- .../Settings/StackWrapperSettings.cs | 35 +++--- .../StackWrapperSettings.injection.cs | 2 +- .../Settings/StackWrapperSettings.mask.cs | 96 +++------------ .../StackWrapperSettings.registration.cs | 116 ++++++++++++++++++ .../Features/Test.InstantiationDiff.cs | 8 +- .../Features/Test.Versioning.cs | 6 +- .../UseCases/Exceptions.cs | 31 ++--- .../UseCases/Sync.cs | 32 ++--- 13 files changed, 236 insertions(+), 179 deletions(-) rename StackInjector/{Injector.defaults.cs => Settings/DefaultConstants.cs} (87%) create mode 100644 StackInjector/Settings/StackWrapperSettings.registration.cs diff --git a/StackInjector/Core/Cloning/ClonedCore.cs b/StackInjector/Core/Cloning/ClonedCore.cs index 59bc858..a6f80cc 100644 --- a/StackInjector/Core/Cloning/ClonedCore.cs +++ b/StackInjector/Core/Cloning/ClonedCore.cs @@ -20,8 +20,9 @@ public IAsyncStackWrapper ToAsyncWrapper ( }; this.clonedCore.EntryType = typeof(TEntry); - if( this.clonedCore.settings.MaskOptions._registerAfterCloning ) - this.clonedCore.ReadAssemblies(); + //todo check this + //if( this.clonedCore.settings.MaskOptions._registerAfterCloning ) + // this.clonedCore.ReadAssemblies(); this.clonedCore.ServeAll(cloned:true); return wrapper; @@ -32,8 +33,9 @@ public IStackWrapper ToWrapper () var wrapper = new StackWrapper(this.clonedCore); this.clonedCore.EntryType = typeof(T); - if( this.clonedCore.settings.MaskOptions._registerAfterCloning ) - this.clonedCore.ReadAssemblies(); + //todo check this + //if( this.clonedCore.settings.MaskOptions._registerAfterCloning ) + // this.clonedCore.ReadAssemblies(); this.clonedCore.ServeAll(cloned:true); return wrapper; diff --git a/StackInjector/Core/StackWrapperCore.cs b/StackInjector/Core/StackWrapperCore.cs index a4792e0..e2c23f7 100644 --- a/StackInjector/Core/StackWrapperCore.cs +++ b/StackInjector/Core/StackWrapperCore.cs @@ -22,13 +22,14 @@ public StackWrapperCore ( InjectionCore core, Type toRegister ) { this.Core = core; - // setting for referencing the calling wrapper as a service - if( this.Core.settings.MaskOptions._registerWrapperAsService ) - { - this.Core.instances.AddType(toRegister); - this.Core.instances[toRegister].Clear(); - this.Core.instances[toRegister].AddFirst(this); - } + //! this was critical code. verify + ////// setting for referencing the calling wrapper as a service + ////if( this.Core.settings.MaskOptions._registerWrapperAsService ) + ////{ + //// this.Core.instances.AddType(toRegister); + //// this.Core.instances[toRegister].Clear(); + //// this.Core.instances[toRegister].AddFirst(this); + ////} } @@ -52,7 +53,7 @@ public IClonedCore CloneCore ( StackWrapperSettings settings = null ) public IClonedCore DeepCloneCore ( StackWrapperSettings settings = null ) { - var clonedCore = new InjectionCore( settings ?? this.Core.settings.Copy() ) + var clonedCore = new InjectionCore( settings ?? this.Core.settings.Clone() ) { instances = this.Core.instances.CloneStructure() }; diff --git a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs b/StackInjector/Core/injectionCore/InjectionCore.reflection.cs index 41fb31c..8598d03 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.reflection.cs @@ -35,31 +35,31 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr } - // reads all [Service] classes - internal void ReadAssemblies () - { - if( this.settings.MaskOptions._registerEntryPointAssembly ) - this.settings.MaskOptions._registredAssemblies.Add(this.EntryType.Assembly); + ////reads all [Service] classes + ////internal void ReadAssemblies () + ////{ + //// if ( this.settings.MaskOptions._registerEntryPointAssembly ) + //// this.settings.MaskOptions._registredAssemblies.Add(this.EntryType.Assembly); - foreach - ( - var t in this - .settings - .MaskOptions - ._registredAssemblies - .SelectMany - ( - assembly => - assembly - .GetTypes() - .AsParallel() - .Where(t => t.IsClass && t.GetCustomAttribute() != null) - ) - ) - { - this.instances.AddType(t); - } - } + //// foreach + //// ( + //// var t in this + //// .settings + //// .MaskOptions + //// ._registredAssemblies + //// .SelectMany + //// ( + //// assembly => + //// assembly + //// .GetTypes() + //// .AsParallel() + //// .Where(t => t.IsClass && t.GetCustomAttribute() != null) + //// ) + //// ) + //// { + //// this.instances.AddType(t); + //// } + ////} } } diff --git a/StackInjector/Injector.cs b/StackInjector/Injector.cs index 31a2c57..989e8df 100644 --- a/StackInjector/Injector.cs +++ b/StackInjector/Injector.cs @@ -29,7 +29,7 @@ public static partial class Injector public static IStackWrapper From ( StackWrapperSettings settings = null ) { if( settings == null ) - settings = StackWrapperSettings.Default(); + settings = StackWrapperSettings.Default; // create the core and wrap it var core = new InjectionCore( settings ) @@ -40,7 +40,7 @@ public static IStackWrapper From ( StackWrapperSettings settings = null ) var wrapper = new StackWrapper(core); // initialize the injection process - core.ReadAssemblies(); + ////core.ReadAssemblies(); core.ServeAll(); @@ -72,7 +72,7 @@ public static IAsyncStackWrapper AsyncFrom ) { if( settings == null ) - settings = StackWrapperSettings.Default(); + settings = StackWrapperSettings.Default; // create the core and wrap it var core = new InjectionCore( settings ) @@ -86,7 +86,7 @@ public static IAsyncStackWrapper AsyncFrom }; // initialize the injection process - core.ReadAssemblies(); + ////core.ReadAssemblies(); core.ServeAll(); return wrapper; diff --git a/StackInjector/Injector.defaults.cs b/StackInjector/Settings/DefaultConstants.cs similarity index 87% rename from StackInjector/Injector.defaults.cs rename to StackInjector/Settings/DefaultConstants.cs index 846688d..17c947b 100644 --- a/StackInjector/Injector.defaults.cs +++ b/StackInjector/Settings/DefaultConstants.cs @@ -1,14 +1,14 @@ using StackInjector.Attributes; using StackInjector.Settings; -namespace StackInjector +namespace StackInjector.Settings { - public static partial class Injector + public partial class StackWrapperSettings { /// /// Static class for default settings. /// - public static class Defaults + public static class DefaultConstants { // the const keyword allows usage in attributes diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 7988ad8..c608d05 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -13,9 +13,15 @@ public sealed partial class StackWrapperSettings { public Mask MaskOptions { get; private set; } + public Injection InjectionOptions { get; private set; } + public Runtime RuntimeOptions { get; private set; } +#if FEATURE_REGISTRATION + public Registration RegistrationOptions {get; private set;} +#endif + private StackWrapperSettings () { } @@ -24,32 +30,26 @@ private StackWrapperSettings () { } /// creates a deep copy of this settings object /// /// - public StackWrapperSettings Copy () + public StackWrapperSettings Clone () { - var settingsCopy = (StackWrapperSettings)this.MemberwiseClone(); + //todo implement Clone() in every suboption + throw new NotImplementedException(); + var settingsCopy = Default; // creats a deep copy of reference objects - settingsCopy.MaskOptions._registredAssemblies = this.MaskOptions._registredAssemblies.ToHashSet(); + //settingsCopy.MaskOptions._registredAssemblies = this.MaskOptions._registredAssemblies.ToHashSet(); return settingsCopy; } - - /// - /// generates a new with everything set to false - /// - /// empty settings - public static StackWrapperSettings Empty - => - new StackWrapperSettings(); - + public static StackWrapperSettings Default => With(null, null, null); - public static StackWrapperSettings Default ( Injection injection = null, Runtime runtime = null, Mask mask = null ) + public static StackWrapperSettings With ( Injection injection, Runtime runtime, Mask mask ) => new StackWrapperSettings() { - MaskOptions = mask ?? Mask.Default, + MaskOptions = mask ?? Mask.BlackList, InjectionOptions = injection ?? Injection.Default, RuntimeOptions = runtime ?? Runtime.Default }; @@ -61,7 +61,12 @@ public static StackWrapperSettings Default ( Injection injection = null, Runtime /// /// public static StackWrapperSettings DefaultBySubtraction - => Default(Injection.Default.InjectionServingMethods(Injector.Defaults.ServeAll, true)); + => With( + Injection.Default + .InjectionServingMethods(DefaultConstants.ServeAll, true), + null, + null + ); } diff --git a/StackInjector/Settings/StackWrapperSettings.injection.cs b/StackInjector/Settings/StackWrapperSettings.injection.cs index d00e62d..6e63aa8 100644 --- a/StackInjector/Settings/StackWrapperSettings.injection.cs +++ b/StackInjector/Settings/StackWrapperSettings.injection.cs @@ -12,7 +12,7 @@ public sealed class Injection internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; internal bool _overrideTargetingMethod; - internal ServingMethods _servingMethod = Injector.Defaults.ServeAllStrict; + internal ServingMethods _servingMethod = DefaultConstants.ServeAllStrict; internal bool _overrideServingMethod; internal bool _cleanUnusedTypesAftInj; internal uint _limitInstancesCount = 128; diff --git a/StackInjector/Settings/StackWrapperSettings.mask.cs b/StackInjector/Settings/StackWrapperSettings.mask.cs index 7b25ebe..d9380a8 100644 --- a/StackInjector/Settings/StackWrapperSettings.mask.cs +++ b/StackInjector/Settings/StackWrapperSettings.mask.cs @@ -1,110 +1,42 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Reflection; using System.Text; -using System.Text.RegularExpressions; namespace StackInjector.Settings { partial class StackWrapperSettings { - - public sealed class Mask + public sealed class Mask : HashSet { - // registration - internal HashSet _registredAssemblies = new HashSet(); - internal bool _registerEntryPointAssembly = true; - internal bool _registerWrapperAsService = true; - internal bool _registerAfterCloning; - - public static Mask Default => new Mask(); + internal bool isWhiteList; - internal Mask () { } + private Mask () { } - /// - /// Register an external assembly from wich you want classes to be laoded. - /// - /// - /// the modified settings - public Mask RegisterAssemblies ( params Assembly[] assemblies ) + public Mask Register ( params Type[] types ) { - if ( assemblies is null ) - throw new ArgumentNullException(nameof(assemblies)); - - foreach ( var assembly in assemblies ) - this._registredAssemblies.Add(assembly); + foreach ( var t in types ) + base.Add(t); return this; } - /// - /// Automatically register all domain assemblies, filtering the specified ones.
- /// Warning: CPU expensive - ///
- /// a regex string used to filter unwanted matching assemblies - /// the modified settings - public Mask RegisterDomain ( string regexFilter = Injector.Defaults.AssemblyRegexFilter ) + + public bool IsMasked ( Type type ) { - this.RegisterAssemblies - ( - AppDomain.CurrentDomain - .GetAssemblies() - .Where(a => !Regex.IsMatch(a.FullName, regexFilter)) - .ToArray() - ); + if ( isWhiteList ) + return this.Contains(type); + else + return !this.Contains(type); - return this; } - /// - /// Register the assembly of the specified type. - /// Same as . - /// - /// - /// the modified settings - public Mask RegisterAssemblyOf () - { - this.RegisterAssemblies(typeof(T).Assembly); - return this; - } - /// - /// Register the entry point assembly when starting. - /// If set, there is no need to specify the entry assembly in . - /// Default is true. - /// - /// the modified settings - public Mask RegisterEntryAssembly ( bool register = true ) - { - this._registerEntryPointAssembly = register; - return this; - } - /// - /// Register the wrapper as a service, so it can be accessed in contained classes. - /// Default is true. - /// - /// the modified settings - public Mask RegisterWrapperAsService ( bool register = true ) - { - this._registerWrapperAsService = register; - return this; - } + public static Mask WhiteList => new Mask() { isWhiteList = true }; + public static Mask BlackList => new Mask(); - /// - /// If set, when cloned the StackWrapper will re-scans all assemblies before the injection. - /// Used to update assemblies with new types. - /// - /// the modified settings - public Mask RegisterAfterCloning ( bool register = true ) - { - this._registerAfterCloning = register; - return this; - } } - } } diff --git a/StackInjector/Settings/StackWrapperSettings.registration.cs b/StackInjector/Settings/StackWrapperSettings.registration.cs new file mode 100644 index 0000000..e96f906 --- /dev/null +++ b/StackInjector/Settings/StackWrapperSettings.registration.cs @@ -0,0 +1,116 @@ + +#if FEATURE_REGISTRATION + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; + +namespace StackInjector.Settings +{ + + partial class StackWrapperSettings + { + + public sealed class Registration + { + // registration + internal HashSet _registredAssemblies = new HashSet(); + internal bool _registerEntryPointAssembly = true; + internal bool _registerWrapperAsService = true; + internal bool _registerAfterCloning; + + public static Registration Default => new Registration(); + + internal Registration () { } + + + /// + /// Register an external assembly from wich you want classes to be laoded. + /// + /// + /// the modified settings + public Registration RegisterAssemblies ( params Assembly[] assemblies ) + { + if ( assemblies is null ) + throw new ArgumentNullException(nameof(assemblies)); + + foreach ( var assembly in assemblies ) + this._registredAssemblies.Add(assembly); + return this; + } + + /// + /// Automatically register all domain assemblies, filtering the specified ones.
+ /// Warning: CPU expensive + ///
+ /// a regex string used to filter unwanted matching assemblies + /// the modified settings + public Registration RegisterDomain ( string regexFilter = Injector.Defaults.AssemblyRegexFilter ) + { + this.RegisterAssemblies + ( + AppDomain.CurrentDomain + .GetAssemblies() + .Where(a => !Regex.IsMatch(a.FullName, regexFilter)) + .ToArray() + ); + + return this; + } + + /// + /// Register the assembly of the specified type. + /// Same as . + /// + /// + /// the modified settings + public Registration RegisterAssemblyOf () + { + this.RegisterAssemblies(typeof(T).Assembly); + return this; + } + + /// + /// Register the entry point assembly when starting. + /// If set, there is no need to specify the entry assembly in . + /// Default is true. + /// + /// the modified settings + public Registration RegisterEntryAssembly ( bool register = true ) + { + this._registerEntryPointAssembly = register; + return this; + } + + /// + /// Register the wrapper as a service, so it can be accessed in contained classes. + /// Default is true. + /// + /// the modified settings + public Registration RegisterWrapperAsService ( bool register = true ) + { + this._registerWrapperAsService = register; + return this; + } + + + /// + /// If set, when cloned the StackWrapper will re-scans all assemblies before the injection. + /// Used to update assemblies with new types. + /// + /// the modified settings + public Registration RegisterAfterCloning ( bool register = true ) + { + this._registerAfterCloning = register; + return this; + } + + } + + } +} + +#endif \ No newline at end of file diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs index e65a697..a6578c5 100644 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs +++ b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs @@ -31,7 +31,7 @@ private class ServiceA [Test] public void SimpleClone () { - var settings = StackWrapperSettings.Default(); + var settings = StackWrapperSettings.Default; settings.InjectionOptions .TrackInstantiationDiff(); @@ -57,7 +57,7 @@ public void SimpleClone () [Test] public void SimpleCloneWithDispose () { - var settings = StackWrapperSettings.Default(); + var settings = StackWrapperSettings.Default; settings.InjectionOptions .TrackInstantiationDiff(); @@ -78,7 +78,7 @@ public void SimpleCloneWithDispose () [Test] public void DeepClone () { - var settings = StackWrapperSettings.Default(); + var settings = StackWrapperSettings.Default; settings.InjectionOptions .TrackInstantiationDiff(); @@ -103,7 +103,7 @@ public void DeepClone () [Test] public void DeepCloneWithDispose () { - var settings = StackWrapperSettings.Default(); + var settings = StackWrapperSettings.Default; settings.InjectionOptions .TrackInstantiationDiff(); diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs index 020ea9a..f6c7f79 100644 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs +++ b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs @@ -13,7 +13,7 @@ internal class Versioning : CommonTestingMethods [Test] public void ServedVersioningClass () { - var settings = StackWrapperSettings.Default(); + var settings = StackWrapperSettings.Default; settings.InjectionOptions .InjectionVersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); @@ -38,7 +38,7 @@ public void ServedVersioningInterface () [Test] public void SettingVersioningLatestMaj () { - var settings = StackWrapperSettings.Default(); + var settings = StackWrapperSettings.Default; settings.InjectionOptions .InjectionVersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); @@ -51,7 +51,7 @@ public void SettingVersioningLatestMaj () [Test] public void SettingVersioningLatestMin () { - var settings = StackWrapperSettings.Default(); + var settings = StackWrapperSettings.Default; settings.InjectionOptions .InjectionVersioningMethod(ServedVersionTargetingMethod.LatestMinor,true); diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index f5af517..10c911d 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -48,32 +48,33 @@ public void ThrowsServiceNotFound () => Assert.Throws(() => Injector.From()); - [Test] + [Test][Ignore("feature disabled. Review")] public void ExternalAssemblyReference () { - var settings = SWS.Default( - mask: - SWS.Mask.Default - .RegisterAssemblyOf() - ); + //var settings = SWS.Default( + // mask: + // SWS.Registration.Default + // .RegisterAssemblyOf() + // ); - var externalClass = Injector.From(settings).Entry.externalClass; + //var externalClass = Injector.From(settings).Entry.externalClass; - Assert.That(externalClass, Is.TypeOf()); + //Assert.That(externalClass, Is.TypeOf()); } [Test] + [Ignore("feature disabled. Review")] public void ExternalAllAssemblyReference () { - var settings = SWS.Default(); - settings.MaskOptions.RegisterDomain(); + //var settings = SWS.With(); + //settings.MaskOptions.RegisterDomain(); - var externalClass = Injector.From(settings).Entry.externalClass; + //var externalClass = Injector.From(settings).Entry.externalClass; - Assert.That(externalClass, Is.TypeOf()); + //Assert.That(externalClass, Is.TypeOf()); } @@ -144,7 +145,7 @@ public void NotThrowsInstLimitReach_Singleton_wBase () { ExecuteTest(100, () => { - var settings = SWS.Default(); + var settings = SWS.Default; settings.InjectionOptions .LimitInstancesCount(2); Assert.DoesNotThrow(() => Injector.From(settings)); @@ -158,7 +159,7 @@ public void NotThrowsInstLimitReach_Singleton () { ExecuteTest(100, () => { - var settings = SWS.Default(); + var settings = SWS.Default; settings.InjectionOptions.LimitInstancesCount(2); Assert.DoesNotThrow(() => Injector.From(settings)); }); @@ -171,7 +172,7 @@ public void NotThrowsInstLimitReach_Singleton () [Timeout(500)] public void ThrowsInstLimitReach_Cloned () { - var settings = SWS.Default(); + var settings = SWS.Default; settings.InjectionOptions .LimitInstancesCount(1); Assert.Throws( () => Injector.From().CloneCore(settings).ToWrapper() ); diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs index 89466b1..e36fb53 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs @@ -44,9 +44,9 @@ public void FromInterface () [Test] public void ServeStrict () { - var settings = StackWrapperSettings.Default(); + var settings = StackWrapperSettings.Default; settings.InjectionOptions - .InjectionServingMethods( Injector.Defaults.ServeAllStrict, true ); + .InjectionServingMethods( StackWrapperSettings.DefaultConstants.ServeAllStrict, true ); var entry = Injector.From(settings).Entry; @@ -58,7 +58,7 @@ public void ServeStrict () public void RemoveUnusedTypes () { var settings = - StackWrapperSettings.Default(); + StackWrapperSettings.Default; settings.InjectionOptions .RemoveUnusedTypesAfterInjection(); @@ -118,25 +118,25 @@ public void AlwaysCreate () internal class Cloning { - [Test] + [Test][Ignore("feature removed. Review this later")] public void RegisterAfterCloning () { - // empty class - var wrapper1 = Injector.From(); + ////// empty class + ////var wrapper1 = Injector.From(); - Assert.Multiple(() => - { - // BaseServiceNotFoundThrower uses a class in an external assembly - Assert.Throws(() => wrapper1.CloneCore().ToWrapper()); + ////Assert.Multiple(() => + ////{ + //// // BaseServiceNotFoundThrower uses a class in an external assembly + //// Assert.Throws(() => wrapper1.CloneCore().ToWrapper()); - var settings = StackWrapperSettings.Default(); - settings.MaskOptions - .RegisterAssemblyOf() - .RegisterAfterCloning(); + //// var settings = StackWrapperSettings.Default; + //// settings.MaskOptions + //// .RegisterAssemblyOf() + //// .RegisterAfterCloning(); - Assert.DoesNotThrow(() => wrapper1.CloneCore(settings).ToWrapper()); + //// Assert.DoesNotThrow(() => wrapper1.CloneCore(settings).ToWrapper()); - }); + //}); } From 92200b1d463aedf72ba5df0ddbefa7225ccddd18 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sun, 21 Feb 2021 18:54:19 +0100 Subject: [PATCH 06/26] major internal refactoring completly dropped type Registration - assembly search is done when versioning interfaces - check IsMasked in .reflection - moved .logic in .serve - disabled feature-specific tests - added Mask.Disabled --- StackInjector/Core/Cloning/ClonedCore.cs | 4 +- .../InjectionCore.serve.cs} | 8 +-- StackInjector/Core/StackWrapperCore.cs | 21 ++++--- .../Core/injectionCore/InjectionCore.cs | 1 + .../InjectionCore.instantiation.cs | 55 ++++++++++--------- .../injectionCore/InjectionCore.reflection.cs | 30 ++++++++-- .../injectionCore/InjectionCore.versioning.cs | 7 ++- .../Core/injectionCore/InstancesHolder.cs | 31 +++++------ StackInjector/Injector.cs | 4 +- .../Settings/StackWrapperSettings.cs | 4 +- .../Settings/StackWrapperSettings.mask.cs | 15 +++-- .../UseCases/Exceptions.cs | 25 ++++----- .../UseCases/Sync.cs | 2 + 13 files changed, 118 insertions(+), 89 deletions(-) rename StackInjector/Core/{injectionCore/InjectionCore.logic.cs => InjectionCore/InjectionCore.serve.cs} (91%) diff --git a/StackInjector/Core/Cloning/ClonedCore.cs b/StackInjector/Core/Cloning/ClonedCore.cs index a6f80cc..4c18fbc 100644 --- a/StackInjector/Core/Cloning/ClonedCore.cs +++ b/StackInjector/Core/Cloning/ClonedCore.cs @@ -23,7 +23,7 @@ public IAsyncStackWrapper ToAsyncWrapper ( //todo check this //if( this.clonedCore.settings.MaskOptions._registerAfterCloning ) // this.clonedCore.ReadAssemblies(); - this.clonedCore.ServeAll(cloned:true); + this.clonedCore.Serve(cloned:true); return wrapper; } @@ -36,7 +36,7 @@ public IStackWrapper ToWrapper () //todo check this //if( this.clonedCore.settings.MaskOptions._registerAfterCloning ) // this.clonedCore.ReadAssemblies(); - this.clonedCore.ServeAll(cloned:true); + this.clonedCore.Serve(cloned:true); return wrapper; } diff --git a/StackInjector/Core/injectionCore/InjectionCore.logic.cs b/StackInjector/Core/InjectionCore/InjectionCore.serve.cs similarity index 91% rename from StackInjector/Core/injectionCore/InjectionCore.logic.cs rename to StackInjector/Core/InjectionCore/InjectionCore.serve.cs index 0bc4ed0..c64d530 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.logic.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.serve.cs @@ -7,7 +7,7 @@ namespace StackInjector.Core internal partial class InjectionCore { - internal void ServeAll ( bool cloned = false ) + internal void Serve ( bool cloned = false ) { // those don't need to be inside the lock. var injected = new HashSet(); @@ -20,15 +20,13 @@ internal void ServeAll ( bool cloned = false ) // ensures that two threads are not trying to Dispose/InjectAll at the same time lock( this._lock ) { - // entry type must always be a class + // EntryType must be a class this.EntryType = this.ClassOrVersionFromInterface(this.EntryType); - // instantiates and enqueues the EntryPoint + // instantiates and enqueues the EntryPoint. initializes the loop toInject.Enqueue(this.OfTypeOrInstantiate(this.EntryType)); - checkInstancesLimit(); - // enqueuing loop while( toInject.Any() ) { diff --git a/StackInjector/Core/StackWrapperCore.cs b/StackInjector/Core/StackWrapperCore.cs index e2c23f7..bab3a1a 100644 --- a/StackInjector/Core/StackWrapperCore.cs +++ b/StackInjector/Core/StackWrapperCore.cs @@ -22,23 +22,22 @@ public StackWrapperCore ( InjectionCore core, Type toRegister ) { this.Core = core; - //! this was critical code. verify - ////// setting for referencing the calling wrapper as a service - ////if( this.Core.settings.MaskOptions._registerWrapperAsService ) - ////{ - //// this.Core.instances.AddType(toRegister); - //// this.Core.instances[toRegister].Clear(); - //// this.Core.instances[toRegister].AddFirst(this); - ////} + //x setting for referencing the calling wrapper as a service + //x if( this.Core.settings.MaskOptions._registerWrapperAsService ) + + if ( !this.Core.instances.AddType(toRegister) ) + this.Core.instances[toRegister].Clear(); + this.Core.instances[toRegister].AddFirst(this); + } public IEnumerable GetServices () { return this.Core - .instances - .InstancesAssignableFrom(typeof(T)) - .Select(o => (T)o); + .instances + .InstancesAssignableFrom(typeof(T)) + .Select(o => (T)o); } public IClonedCore CloneCore ( StackWrapperSettings settings = null ) diff --git a/StackInjector/Core/injectionCore/InjectionCore.cs b/StackInjector/Core/injectionCore/InjectionCore.cs index e37189a..0a013af 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.cs @@ -40,6 +40,7 @@ internal Type EntryType internal InstancesHolder instances; // tracks instantiated objects + //todo move into instancesHolder internal readonly List instancesDiff; // used to lock this core on critical sections diff --git a/StackInjector/Core/injectionCore/InjectionCore.instantiation.cs b/StackInjector/Core/injectionCore/InjectionCore.instantiation.cs index f750631..9430951 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.instantiation.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.instantiation.cs @@ -9,51 +9,52 @@ namespace StackInjector.Core { internal partial class InjectionCore { + private object OfTypeOrInstantiate ( Type type ) + { + var serviceAtt = type.GetCustomAttribute(); + + // manage exceptions + 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 + { + InstantiationPattern.AlwaysCreate + => this.InstantiateService(type), + _ + => (this.instances.ContainsKey(type) && this.instances[type].Any()) + ? this.instances[type].First() + : this.InstantiateService(type), + }; + } + + // Instantiates the specified [Served] type private object InstantiateService ( Type type ) { type = this.ClassOrVersionFromInterface(type); - - if( type.GetConstructor(Array.Empty()) == null ) + //todo add more constructor options + if ( type.GetConstructor(Array.Empty()) == null ) throw new MissingParameterlessConstructorException(type, $"Missing parameteless constructor for {type.FullName}"); var instance = Activator.CreateInstance(type); - + this.instances.AddType(type); //try add this.instances[type].AddLast(instance); this.instances.total_count++; // if true, track instantiated objects - if( this.settings.InjectionOptions._trackInstancesDiff ) + if ( this.settings.InjectionOptions._trackInstancesDiff ) this.instancesDiff.Add(instance); return instance; } - private object OfTypeOrInstantiate ( Type type ) - { - var serviceAtt = type.GetCustomAttribute(); - - // manage exceptions - if( serviceAtt == null ) - throw new NotAServiceException(type, $"The type {type.FullName} is not annotated with [Service]"); - - //todo 4.0: allow disabling of this check and add services at runtime - if( !this.instances.ContainsKey(type) ) - throw new ServiceNotFoundException(type, $"The type {type.FullName} is not in a registred assembly!"); - - - return serviceAtt.Pattern switch - { - InstantiationPattern.AlwaysCreate - => this.InstantiateService(type), - _ - => (this.instances[type].Any()) - ? this.instances[type].First() - : this.InstantiateService(type), - }; - } } } diff --git a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs b/StackInjector/Core/injectionCore/InjectionCore.reflection.cs index 8598d03..39c7294 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.reflection.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Threading; using StackInjector.Attributes; using StackInjector.Exceptions; @@ -14,15 +16,24 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr { if( type.IsInterface ) { - var versions = this.Version(type, servedAttribute); + IEnumerable versions = this.instances.TypesAssignableFrom(type); - if( versions.Any() ) + // is there already an implementation for the interface? + if ( versions.Any() ) { return versions.First(); } else { - if( servedAttribute is null ) + versions = this.Version(type, servedAttribute); + if ( versions.Any() ) + { + 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}"); @@ -30,11 +41,22 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr } else { + MaskPass(type); return type; } - } + void MaskPass (Type type) + { + if ( !this.settings.MaskOptions._isDisabled && this.settings.MaskOptions.IsMasked(type) ) + throw new Exception($"Type {type.Name} is { (this.settings.MaskOptions._isWhiteList ? "not in the whitelist" : "in the blacklist")}"); + //todo create custom exception + } + + + } + + // moved to InjectionCore.versioning.cs ////reads all [Service] classes ////internal void ReadAssemblies () ////{ diff --git a/StackInjector/Core/injectionCore/InjectionCore.versioning.cs b/StackInjector/Core/injectionCore/InjectionCore.versioning.cs index d2a31e9..10e3013 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.versioning.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.versioning.cs @@ -19,7 +19,12 @@ private IEnumerable Version ( Type targetType, ServedAttribute servedAttri ? this.settings.InjectionOptions._targetingMethod : servedAttribute.TargetingMethod; - var candidateTypes = this.instances.TypesAssignableFrom(targetType); + + ////var candidateTypes = this.instances.TypesAssignableFrom(targetType); + var candidateTypes = targetType + .Assembly + .GetTypes() + .Where( t => t.IsClass && !t.IsAbstract && targetType.IsAssignableFrom(t)); return method switch diff --git a/StackInjector/Core/injectionCore/InstancesHolder.cs b/StackInjector/Core/injectionCore/InstancesHolder.cs index 7a5f7d5..521f92d 100644 --- a/StackInjector/Core/injectionCore/InstancesHolder.cs +++ b/StackInjector/Core/injectionCore/InstancesHolder.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; namespace StackInjector.Core @@ -8,24 +9,21 @@ internal class InstancesHolder : Dictionary> { internal uint total_count = 0; - internal IEnumerable TypesAssignableFrom ( Type type ) - { - return this - .Keys - .Where(t => type.IsAssignableFrom(t)); - } + internal IEnumerable TypesAssignableFrom ( Type type ) => + this + .Keys + .Where(t => type.IsAssignableFrom(t)); + - internal IEnumerable InstancesAssignableFrom ( Type type ) - { - return this - .Where(pair => type.IsAssignableFrom(pair.Key) && pair.Value.Any()) - .SelectMany(pair => pair.Value); - } + internal IEnumerable InstancesAssignableFrom ( Type type ) => + this + .Where(pair => type.IsAssignableFrom(pair.Key) && pair.Value.Any()) + .SelectMany(pair => pair.Value); + - internal void AddType ( Type type ) - { - this.TryAdd(type, new LinkedList()); - } + internal bool AddType ( Type type ) => + this.TryAdd(type, new LinkedList() ); + internal void CountAllInstances () @@ -36,6 +34,7 @@ internal void CountAllInstances () } + //todo review // clones just the structure, the classes references are not cloned internal InstancesHolder CloneStructure () { diff --git a/StackInjector/Injector.cs b/StackInjector/Injector.cs index 989e8df..6ff43a0 100644 --- a/StackInjector/Injector.cs +++ b/StackInjector/Injector.cs @@ -41,7 +41,7 @@ public static IStackWrapper From ( StackWrapperSettings settings = null ) // initialize the injection process ////core.ReadAssemblies(); - core.ServeAll(); + core.Serve(); return wrapper; @@ -87,7 +87,7 @@ public static IAsyncStackWrapper AsyncFrom // initialize the injection process ////core.ReadAssemblies(); - core.ServeAll(); + core.Serve(); return wrapper; } diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index c608d05..25f14ad 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -32,7 +32,7 @@ private StackWrapperSettings () { } /// public StackWrapperSettings Clone () { - //todo implement Clone() in every suboption + //! implement Clone() in every suboption throw new NotImplementedException(); var settingsCopy = Default; // creats a deep copy of reference objects @@ -49,7 +49,7 @@ public static StackWrapperSettings With ( Injection injection, Runtime runtime, => new StackWrapperSettings() { - MaskOptions = mask ?? Mask.BlackList, + MaskOptions = mask ?? Mask.Disabled, InjectionOptions = injection ?? Injection.Default, RuntimeOptions = runtime ?? Runtime.Default }; diff --git a/StackInjector/Settings/StackWrapperSettings.mask.cs b/StackInjector/Settings/StackWrapperSettings.mask.cs index d9380a8..604c5bb 100644 --- a/StackInjector/Settings/StackWrapperSettings.mask.cs +++ b/StackInjector/Settings/StackWrapperSettings.mask.cs @@ -8,13 +8,15 @@ partial class StackWrapperSettings { public sealed class Mask : HashSet { - internal bool isWhiteList; + internal bool _isDisabled; + internal bool _isWhiteList; private Mask () { } public Mask Register ( params Type[] types ) { + this._isDisabled = false; foreach ( var t in types ) base.Add(t); return this; @@ -23,18 +25,19 @@ public Mask Register ( params Type[] types ) public bool IsMasked ( Type type ) { - if ( isWhiteList ) - return this.Contains(type); - else + if ( _isWhiteList ) return !this.Contains(type); + else + return this.Contains(type); } + public static Mask WhiteList => new Mask() { _isWhiteList = true }; - public static Mask WhiteList => new Mask() { isWhiteList = true }; + public static Mask BlackList => new Mask(); - public static Mask BlackList => new Mask(); + public static Mask Disabled => new Mask() { _isDisabled = true }; } diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index 10c911d..e935236 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -41,31 +41,30 @@ public void ThrowsBaseNotAService () // references class in unregistred external assembly [Service] - internal class BaseServiceNotFoundThrower {[Served] public Externalclass externalClass; } + internal class ClassInExternalAssemblyBase {[Served] public Externalclass externalClass; } [Test] public void ThrowsServiceNotFound () - => Assert.Throws(() => Injector.From()); + { + var settings = SWS.Default; + // add to blacklist + settings.MaskOptions.Register(typeof(Externalclass)); + + Assert.Throws(() => Injector.From(settings)); + } - [Test][Ignore("feature disabled. Review")] + [Test] public void ExternalAssemblyReference () { - //var settings = SWS.Default( - // mask: - // SWS.Registration.Default - // .RegisterAssemblyOf() - // ); - - - //var externalClass = Injector.From(settings).Entry.externalClass; + var externalClass = Injector.From().Entry.externalClass; - //Assert.That(externalClass, Is.TypeOf()); + Assert.That(externalClass, Is.TypeOf()); } [Test] - [Ignore("feature disabled. Review")] + [Ignore("feature disabled.")] public void ExternalAllAssemblyReference () { //var settings = SWS.With(); diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs index e36fb53..d810234 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs @@ -10,6 +10,8 @@ #pragma warning disable CS0649 namespace StackInjector.TEST.BlackBox.UseCases { + + //todo add test for abastract classes internal class Sync : CommonTestingMethods { From 5e485faf546415c139bbb3308292b1a20e296917 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Mon, 22 Feb 2021 19:01:13 +0100 Subject: [PATCH 07/26] add StackWrapperSettings.IOptions - will serve as a starting point for expanding modular settings --- .../Settings/StackWrapperSettings.Options.cs | 19 +++++++++++++++++ .../Settings/StackWrapperSettings.cs | 19 ++++++----------- .../StackWrapperSettings.injection.cs | 18 +++++++++------- .../Settings/StackWrapperSettings.mask.cs | 9 +++++++- .../Settings/StackWrapperSettings.runtime.cs | 7 ++++++- .../Features/Test.InstantiationDiff.cs | 21 ++++++++++++------- .../UseCases/Exceptions.cs | 3 ++- .../UseCases/Sync.cs | 12 +++++------ 8 files changed, 70 insertions(+), 38 deletions(-) create mode 100644 StackInjector/Settings/StackWrapperSettings.Options.cs diff --git a/StackInjector/Settings/StackWrapperSettings.Options.cs b/StackInjector/Settings/StackWrapperSettings.Options.cs new file mode 100644 index 0000000..9e7aef5 --- /dev/null +++ b/StackInjector/Settings/StackWrapperSettings.Options.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StackInjector.Settings +{ + partial class StackWrapperSettings + { + /// + /// base class for StackWrapperSettings options + /// + public interface IOptions : ICloneable + { + protected internal IOptions CreateDefault (); + + } + + } +} diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 25f14ad..4bdf13d 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -18,9 +18,6 @@ public sealed partial class StackWrapperSettings public Runtime RuntimeOptions { get; private set; } -#if FEATURE_REGISTRATION - public Registration RegistrationOptions {get; private set;} -#endif private StackWrapperSettings () { } @@ -30,16 +27,12 @@ private StackWrapperSettings () { } /// creates a deep copy of this settings object /// /// - public StackWrapperSettings Clone () - { - //! implement Clone() in every suboption - throw new NotImplementedException(); - var settingsCopy = Default; - // creats a deep copy of reference objects - //settingsCopy.MaskOptions._registredAssemblies = this.MaskOptions._registredAssemblies.ToHashSet(); - - return settingsCopy; - } + public StackWrapperSettings Clone () => + With( + (Injection)this.InjectionOptions.Clone(), + (Runtime)this.RuntimeOptions.Clone(), + (Mask)this.MaskOptions.Clone() + ); public static StackWrapperSettings Default => With(null, null, null); diff --git a/StackInjector/Settings/StackWrapperSettings.injection.cs b/StackInjector/Settings/StackWrapperSettings.injection.cs index 6e63aa8..bc94298 100644 --- a/StackInjector/Settings/StackWrapperSettings.injection.cs +++ b/StackInjector/Settings/StackWrapperSettings.injection.cs @@ -7,7 +7,7 @@ namespace StackInjector.Settings partial class StackWrapperSettings { - public sealed class Injection + public sealed class Injection : IOptions { internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; internal bool _overrideTargetingMethod; @@ -26,12 +26,13 @@ public sealed class Injection internal Injection () { } - public static Injection Default => - new Injection(); - //.TrackInstantiationDiff(false, false) - //.InjectionVersioningMethod(ServedVersionTargetingMethod.None, false) - //.InjectionServingMethods(Injector.Defaults.ServeAllStrict, false) - //.ServeIEnumerables(); + + IOptions IOptions.CreateDefault () => Default; + + public static Injection Default => new Injection(); + + + public object Clone () => MemberwiseClone(); #region configuration methods @@ -79,7 +80,8 @@ public Injection InjectionServingMethods ( ServingMethods methods, bool @overrid /// - /// Remove the reference to unused types after the injection is finished. + /// Remove the reference to unused types after the injection is finished.
+ /// Usually not necessay, but can save memory after cloning ///
/// The modified settings public Injection RemoveUnusedTypesAfterInjection ( bool remove = true ) diff --git a/StackInjector/Settings/StackWrapperSettings.mask.cs b/StackInjector/Settings/StackWrapperSettings.mask.cs index 604c5bb..a50ccc8 100644 --- a/StackInjector/Settings/StackWrapperSettings.mask.cs +++ b/StackInjector/Settings/StackWrapperSettings.mask.cs @@ -6,13 +6,16 @@ namespace StackInjector.Settings { partial class StackWrapperSettings { - public sealed class Mask : HashSet + public sealed class Mask : HashSet, IOptions { internal bool _isDisabled; internal bool _isWhiteList; private Mask () { } + IOptions IOptions.CreateDefault () => Disabled; + + public Mask Register ( params Type[] types ) { @@ -32,6 +35,7 @@ public bool IsMasked ( Type type ) } + public object Clone () => MemberwiseClone(); public static Mask WhiteList => new Mask() { _isWhiteList = true }; @@ -40,6 +44,9 @@ public bool IsMasked ( Type type ) public static Mask Disabled => new Mask() { _isDisabled = true }; + + + } } } diff --git a/StackInjector/Settings/StackWrapperSettings.runtime.cs b/StackInjector/Settings/StackWrapperSettings.runtime.cs index a6efd25..87d5776 100644 --- a/StackInjector/Settings/StackWrapperSettings.runtime.cs +++ b/StackInjector/Settings/StackWrapperSettings.runtime.cs @@ -6,7 +6,7 @@ namespace StackInjector.Settings { partial class StackWrapperSettings { - public sealed class Runtime + public sealed class Runtime : IOptions { // async management @@ -18,6 +18,9 @@ internal Runtime () { } public static Runtime Default => new Runtime(); + IOptions IOptions.CreateDefault () => Default; + + /// /// What to do when an @@ -32,6 +35,8 @@ public Runtime WhenNoMoreTasks ( AsyncWaitingMethod waitingMethod, int waitTime this._asyncWaitTime = waitTime; return this; } + + public object Clone () => this.MemberwiseClone(); } } } diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs index a6578c5..e304afc 100644 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs +++ b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs @@ -1,4 +1,5 @@ using System.Linq; +using NuGet.Frameworks; using NUnit.Framework; using StackInjector.Attributes; using StackInjector.Exceptions; @@ -35,22 +36,23 @@ public void SimpleClone () settings.InjectionOptions .TrackInstantiationDiff(); - IStackWrapper wrapperB; - - var wrapperA = Injector.From(settings); + IStackWrapper wrapperA, wrapperB; - wrapperA.Start(e => e.Work()); + wrapperA = Injector.From(settings); wrapperB = wrapperA.CloneCore().ToWrapper(); Assert.Multiple(() => { Assert.DoesNotThrow(() => wrapperB.Entry.Work()); - Assert.AreSame - ( + Assert.AreSame( wrapperA.GetServices().First(), wrapperB.GetServices().First() ); + Assert.AreSame( + wrapperA.Settings, + wrapperB.Settings + ); }); } @@ -92,11 +94,14 @@ public void DeepClone () Assert.Multiple(() => { Assert.DoesNotThrow(() => wrapperB.Entry.Work()); - Assert.AreNotSame - ( + Assert.AreNotSame( wrapperA.GetServices().First(), wrapperB.GetServices().First() ); + Assert.AreNotSame( + wrapperA.Settings, + wrapperB.Settings + ); }); } diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index e935236..ed8a7ed 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -50,7 +50,8 @@ public void ThrowsServiceNotFound () // add to blacklist settings.MaskOptions.Register(typeof(Externalclass)); - Assert.Throws(() => Injector.From(settings)); + //todo change to specific mask exception + Assert.Throws(() => Injector.From(settings)); } diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs index d810234..db30c7b 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs @@ -56,18 +56,18 @@ public void ServeStrict () } - [Test] + [Test][Ignore("feature has to be reviewd")] public void RemoveUnusedTypes () { - var settings = - StackWrapperSettings.Default; - settings.InjectionOptions + var settings = StackWrapperSettings.Default; + settings.InjectionOptions .RemoveUnusedTypesAfterInjection(); - var wrap1 = Injector.From( settings ); + var wrap1 = Injector.From( settings ); + var clone1 = wrap1.CloneCore(); // base is removed after injecting from a class that doesn't need it - Assert.Throws(() => wrap1.CloneCore().ToWrapper()); + Assert.Throws(() => clone1.ToWrapper()); } From 5d77268f24e192f24ae49c52fdde00a97c057952 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Tue, 23 Feb 2021 23:55:46 +0100 Subject: [PATCH 08/26] Add documentation to StackWrapperSettings.injection --- .../Settings/StackWrapperSettings.cs | 33 ++++++++++++++++--- .../StackWrapperSettings.injection.cs | 32 ++++++++++++++++-- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 4bdf13d..7574a02 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -11,11 +11,19 @@ namespace StackInjector.Settings /// public sealed partial class StackWrapperSettings { - + /// + /// manages masking options. + /// public Mask MaskOptions { get; private set; } + /// + /// manages injection options + /// public Injection InjectionOptions { get; private set; } + /// + /// manages runtime options + /// public Runtime RuntimeOptions { get; private set; } @@ -23,10 +31,11 @@ public sealed partial class StackWrapperSettings private StackWrapperSettings () { } + /// /// creates a deep copy of this settings object /// - /// + /// a cloned settings object public StackWrapperSettings Clone () => With( (Injection)this.InjectionOptions.Clone(), @@ -35,9 +44,22 @@ public StackWrapperSettings Clone () => ); + /// + /// The default settings. see + /// , + /// , + /// + /// public static StackWrapperSettings Default => With(null, null, null); + /// + /// create a new with the specified options. + /// + /// the injection options + /// the runtime options + /// mask options + /// public static StackWrapperSettings With ( Injection injection, Runtime runtime, Mask mask ) => new StackWrapperSettings() @@ -53,11 +75,14 @@ public static StackWrapperSettings With ( Injection injection, Runtime runtime, /// 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( + public static StackWrapperSettings DefaultBySubtraction => + With( + injection: Injection.Default .InjectionServingMethods(DefaultConstants.ServeAll, true), + mask: null, + runtime: null ); diff --git a/StackInjector/Settings/StackWrapperSettings.injection.cs b/StackInjector/Settings/StackWrapperSettings.injection.cs index bc94298..9f6044a 100644 --- a/StackInjector/Settings/StackWrapperSettings.injection.cs +++ b/StackInjector/Settings/StackWrapperSettings.injection.cs @@ -6,7 +6,9 @@ namespace StackInjector.Settings { partial class StackWrapperSettings { - + /// + /// Injection options for the Injector. + /// public sealed class Injection : IOptions { internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; @@ -29,12 +31,38 @@ internal Injection () { } IOptions IOptions.CreateDefault () => Default; + /// + /// The default injection. Settings are valorized as following: + /// + /// + /// + /// , false + /// + /// + /// , false + /// + /// + /// false + /// + /// + /// 128 + /// + /// + /// true + /// + /// + /// false, false + /// + /// + /// public static Injection Default => new Injection(); - + /// public object Clone () => MemberwiseClone(); + + #region configuration methods From 95b84384c1075745ea2e89c7a3ee893b78e14141 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Thu, 25 Feb 2021 22:34:45 +0100 Subject: [PATCH 09/26] add documentation for Mask, IOption, Injection --- .../injectionCore/InjectionCore.reflection.cs | 4 +- .../Settings/StackWrapperSettings.IOption.cs | 25 ++++++++++ .../Settings/StackWrapperSettings.Options.cs | 19 -------- .../Settings/StackWrapperSettings.cs | 2 +- .../StackWrapperSettings.injection.cs | 23 +++++---- .../Settings/StackWrapperSettings.mask.cs | 48 +++++++++++++++---- .../Settings/StackWrapperSettings.runtime.cs | 29 +++++++++-- .../Features/Test.Versioning.cs | 6 +-- .../UseCases/Sync.cs | 2 +- 9 files changed, 105 insertions(+), 53 deletions(-) create mode 100644 StackInjector/Settings/StackWrapperSettings.IOption.cs delete mode 100644 StackInjector/Settings/StackWrapperSettings.Options.cs diff --git a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs b/StackInjector/Core/injectionCore/InjectionCore.reflection.cs index 39c7294..6cc651a 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/injectionCore/InjectionCore.reflection.cs @@ -48,8 +48,8 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr void MaskPass (Type type) { - if ( !this.settings.MaskOptions._isDisabled && this.settings.MaskOptions.IsMasked(type) ) - throw new Exception($"Type {type.Name} is { (this.settings.MaskOptions._isWhiteList ? "not in the whitelist" : "in the blacklist")}"); + if ( this.settings.MaskOptions.IsMasked(type) ) + throw new Exception($"Type {type.Name} is { (this.settings.MaskOptions._isWhiteList ? "not whitelisted" : "blacklisted")}"); //todo create custom exception } diff --git a/StackInjector/Settings/StackWrapperSettings.IOption.cs b/StackInjector/Settings/StackWrapperSettings.IOption.cs new file mode 100644 index 0000000..f2d57ae --- /dev/null +++ b/StackInjector/Settings/StackWrapperSettings.IOption.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StackInjector.Settings +{ + partial class StackWrapperSettings + { + /// + /// Base class for options.
+ /// Options groups are a class of settings grouped by function/scope of use. + ///
+ public interface IOption : ICloneable + { + /// + /// Create a default instance of this options group valorized with default values.
+ /// Default values may differ from uninitialized ones. + ///
+ /// + protected internal IOption CreateDefault (); + + } + + } +} diff --git a/StackInjector/Settings/StackWrapperSettings.Options.cs b/StackInjector/Settings/StackWrapperSettings.Options.cs deleted file mode 100644 index 9e7aef5..0000000 --- a/StackInjector/Settings/StackWrapperSettings.Options.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace StackInjector.Settings -{ - partial class StackWrapperSettings - { - /// - /// base class for StackWrapperSettings options - /// - public interface IOptions : ICloneable - { - protected internal IOptions CreateDefault (); - - } - - } -} diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 7574a02..adf1914 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -79,7 +79,7 @@ public static StackWrapperSettings With ( Injection injection, Runtime runtime, With( injection: Injection.Default - .InjectionServingMethods(DefaultConstants.ServeAll, true), + .ServingMethod(DefaultConstants.ServeAll, true), mask: null, runtime: diff --git a/StackInjector/Settings/StackWrapperSettings.injection.cs b/StackInjector/Settings/StackWrapperSettings.injection.cs index 9f6044a..78d899b 100644 --- a/StackInjector/Settings/StackWrapperSettings.injection.cs +++ b/StackInjector/Settings/StackWrapperSettings.injection.cs @@ -7,9 +7,9 @@ namespace StackInjector.Settings partial class StackWrapperSettings { /// - /// Injection options for the Injector. + /// Options for the injection process. /// - public sealed class Injection : IOptions + public sealed class Injection : IOption { internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; internal bool _overrideTargetingMethod; @@ -29,16 +29,20 @@ public sealed class Injection : IOptions internal Injection () { } - IOptions IOptions.CreateDefault () => Default; + IOption IOption.CreateDefault () => Default; + + /// + public object Clone () => MemberwiseClone(); + /// /// The default injection. Settings are valorized as following: /// /// - /// + /// /// , false /// - /// + /// /// , false /// /// @@ -57,11 +61,6 @@ internal Injection () { } /// public static Injection Default => new Injection(); - /// - public object Clone () => MemberwiseClone(); - - - #region configuration methods @@ -86,7 +85,7 @@ public Injection TrackInstantiationDiff ( bool track = true, bool callDispose = /// the new default targetting method /// if true, versioning methods for [Served] fields and properties are overriden /// the modified settings - public Injection InjectionVersioningMethod ( ServedVersionTargetingMethod targetMethod, bool @override = false ) + public Injection VersioningMethod ( ServedVersionTargetingMethod targetMethod, bool @override = false ) { this._targetingMethod = targetMethod; this._overrideTargetingMethod = @override; @@ -99,7 +98,7 @@ public Injection InjectionVersioningMethod ( ServedVersionTargetingMethod target /// the new default serving method for all services /// if true, serving methods for [Service] calsses are overridden with the specified one /// the modified settings - public Injection InjectionServingMethods ( ServingMethods methods, bool @override = false ) + public Injection ServingMethod ( ServingMethods methods, bool @override = false ) { this._servingMethod = methods; this._overrideServingMethod = @override; diff --git a/StackInjector/Settings/StackWrapperSettings.mask.cs b/StackInjector/Settings/StackWrapperSettings.mask.cs index a50ccc8..3a0d0fe 100644 --- a/StackInjector/Settings/StackWrapperSettings.mask.cs +++ b/StackInjector/Settings/StackWrapperSettings.mask.cs @@ -1,52 +1,80 @@ using System; using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Linq; using System.Text; +using StackInjector.Exceptions; namespace StackInjector.Settings { partial class StackWrapperSettings { - public sealed class Mask : HashSet, IOptions + //todo seealso custom mask exception + /// + /// Used to filter Types from the injection proces. + /// When trying to inject masked Types an injection will be thrown.
+ /// Use to Add multiple types at once. + ///
+ public sealed class Mask : HashSet, IOption { internal bool _isDisabled; internal bool _isWhiteList; private Mask () { } - IOptions IOptions.CreateDefault () => Disabled; - + IOption IOption.CreateDefault () => Disabled; + /// + /// Register multiple Types at once.
+ /// see also + ///
+ /// types to register + /// The modified Mask object public Mask Register ( params Type[] types ) { - this._isDisabled = false; + Contract.Requires(!_isDisabled); //todo test preconditions foreach ( var t in types ) base.Add(t); return this; } + /// + /// Based on the type of mask, if the type is masked_out/forbidden from injection.
+ /// ie: if A is registered and this is a blacklist, IsMasked(A) will return true. + ///
+ /// type to be checked + /// always false when disabled, true if is masked. public bool IsMasked ( Type type ) { - if ( _isWhiteList ) - return !this.Contains(type); + if ( _isDisabled ) + return false; else - return this.Contains(type); + return this._isWhiteList ^ this.Contains(type); //.XOR } + /// public object Clone () => MemberwiseClone(); + + /// + /// allow only registred types. + /// public static Mask WhiteList => new Mask() { _isWhiteList = true }; + /// + /// allow every type except the regisred ones. + /// public static Mask BlackList => new Mask(); + /// + /// allow everything, don't even check. + /// public static Mask Disabled => new Mask() { _isDisabled = true }; - - - } } } diff --git a/StackInjector/Settings/StackWrapperSettings.runtime.cs b/StackInjector/Settings/StackWrapperSettings.runtime.cs index 87d5776..2ded472 100644 --- a/StackInjector/Settings/StackWrapperSettings.runtime.cs +++ b/StackInjector/Settings/StackWrapperSettings.runtime.cs @@ -6,7 +6,10 @@ namespace StackInjector.Settings { partial class StackWrapperSettings { - public sealed class Runtime : IOptions + /// + /// Options used at runtime + /// + public sealed class Runtime : IOption { // async management @@ -16,11 +19,26 @@ public sealed class Runtime : IOptions internal Runtime () { } - public static Runtime Default => new Runtime(); - IOptions IOptions.CreateDefault () => Default; + IOption IOption.CreateDefault () => Default; + + /// + public object Clone () => this.MemberwiseClone(); + + + /// + /// Default runtime options. Settings are valorized as following: + /// + /// + /// + /// , 500 + /// + /// + /// + public static Runtime Default => new Runtime(); + #region configuration methods /// /// What to do when an @@ -29,14 +47,15 @@ internal Runtime () { } /// the new waiting method /// if is set, this will be max time to wait /// the modified settings - public Runtime WhenNoMoreTasks ( AsyncWaitingMethod waitingMethod, int waitTime = 1000 ) + public Runtime WhenNoMoreTasks ( AsyncWaitingMethod waitingMethod, int waitTime ) { this._asyncWaitingMethod = waitingMethod; this._asyncWaitTime = waitTime; return this; } - public object Clone () => this.MemberwiseClone(); + #endregion + } } } diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs index f6c7f79..0bd25cc 100644 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs +++ b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs @@ -15,7 +15,7 @@ public void ServedVersioningClass () { var settings = StackWrapperSettings.Default; settings.InjectionOptions - .InjectionVersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); + .VersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); var versionedService = Injector.From(settings).Entry.Level1_2; @@ -40,7 +40,7 @@ public void SettingVersioningLatestMaj () { var settings = StackWrapperSettings.Default; settings.InjectionOptions - .InjectionVersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); + .VersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); var versionedService = Injector.From( settings ).Entry.level1; @@ -53,7 +53,7 @@ public void SettingVersioningLatestMin () { var settings = StackWrapperSettings.Default; settings.InjectionOptions - .InjectionVersioningMethod(ServedVersionTargetingMethod.LatestMinor,true); + .VersioningMethod(ServedVersionTargetingMethod.LatestMinor,true); var versionedService = Injector.From( settings ).Entry.level1; diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs index db30c7b..38887d9 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs @@ -48,7 +48,7 @@ public void ServeStrict () { var settings = StackWrapperSettings.Default; settings.InjectionOptions - .InjectionServingMethods( StackWrapperSettings.DefaultConstants.ServeAllStrict, true ); + .ServingMethod( StackWrapperSettings.DefaultConstants.ServeAllStrict, true ); var entry = Injector.From(settings).Entry; From 914031dee5e8635129bfc913745f00a29a4740f2 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Thu, 25 Feb 2021 22:52:42 +0100 Subject: [PATCH 10/26] minor adjustments. moved files from [Ii]njectionCore to Core --- .../{injectionCore => Core}/InjectionCore.cs | 0 .../InjectionCore.injection.cs | 0 .../InjectionCore.instantiation.cs | 0 .../InjectionCore.reflection.cs | 27 ------------------- .../InjectionCore.serve.cs | 0 .../InjectionCore.utilities.cs | 0 .../InjectionCore.versioning.cs | 0 .../InstancesHolder.cs | 0 .../Settings/StackWrapperSettings.cs | 4 +-- .../StackWrapperSettings.injection.cs | 4 +-- .../UseCases/Exceptions.cs | 7 ++--- 11 files changed, 8 insertions(+), 34 deletions(-) rename StackInjector/Core/{injectionCore => Core}/InjectionCore.cs (100%) rename StackInjector/Core/{injectionCore => Core}/InjectionCore.injection.cs (100%) rename StackInjector/Core/{injectionCore => Core}/InjectionCore.instantiation.cs (100%) rename StackInjector/Core/{injectionCore => Core}/InjectionCore.reflection.cs (69%) rename StackInjector/Core/{InjectionCore => Core}/InjectionCore.serve.cs (100%) rename StackInjector/Core/{InjectionCore => Core}/InjectionCore.utilities.cs (100%) rename StackInjector/Core/{injectionCore => Core}/InjectionCore.versioning.cs (100%) rename StackInjector/Core/{injectionCore => Core}/InstancesHolder.cs (100%) diff --git a/StackInjector/Core/injectionCore/InjectionCore.cs b/StackInjector/Core/Core/InjectionCore.cs similarity index 100% rename from StackInjector/Core/injectionCore/InjectionCore.cs rename to StackInjector/Core/Core/InjectionCore.cs diff --git a/StackInjector/Core/injectionCore/InjectionCore.injection.cs b/StackInjector/Core/Core/InjectionCore.injection.cs similarity index 100% rename from StackInjector/Core/injectionCore/InjectionCore.injection.cs rename to StackInjector/Core/Core/InjectionCore.injection.cs diff --git a/StackInjector/Core/injectionCore/InjectionCore.instantiation.cs b/StackInjector/Core/Core/InjectionCore.instantiation.cs similarity index 100% rename from StackInjector/Core/injectionCore/InjectionCore.instantiation.cs rename to StackInjector/Core/Core/InjectionCore.instantiation.cs diff --git a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs b/StackInjector/Core/Core/InjectionCore.reflection.cs similarity index 69% rename from StackInjector/Core/injectionCore/InjectionCore.reflection.cs rename to StackInjector/Core/Core/InjectionCore.reflection.cs index 6cc651a..5dacd65 100644 --- a/StackInjector/Core/injectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/Core/InjectionCore.reflection.cs @@ -56,32 +56,5 @@ void MaskPass (Type type) } - // moved to InjectionCore.versioning.cs - ////reads all [Service] classes - ////internal void ReadAssemblies () - ////{ - //// if ( this.settings.MaskOptions._registerEntryPointAssembly ) - //// this.settings.MaskOptions._registredAssemblies.Add(this.EntryType.Assembly); - - //// foreach - //// ( - //// var t in this - //// .settings - //// .MaskOptions - //// ._registredAssemblies - //// .SelectMany - //// ( - //// assembly => - //// assembly - //// .GetTypes() - //// .AsParallel() - //// .Where(t => t.IsClass && t.GetCustomAttribute() != null) - //// ) - //// ) - //// { - //// this.instances.AddType(t); - //// } - ////} - } } diff --git a/StackInjector/Core/InjectionCore/InjectionCore.serve.cs b/StackInjector/Core/Core/InjectionCore.serve.cs similarity index 100% rename from StackInjector/Core/InjectionCore/InjectionCore.serve.cs rename to StackInjector/Core/Core/InjectionCore.serve.cs diff --git a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs b/StackInjector/Core/Core/InjectionCore.utilities.cs similarity index 100% rename from StackInjector/Core/InjectionCore/InjectionCore.utilities.cs rename to StackInjector/Core/Core/InjectionCore.utilities.cs diff --git a/StackInjector/Core/injectionCore/InjectionCore.versioning.cs b/StackInjector/Core/Core/InjectionCore.versioning.cs similarity index 100% rename from StackInjector/Core/injectionCore/InjectionCore.versioning.cs rename to StackInjector/Core/Core/InjectionCore.versioning.cs diff --git a/StackInjector/Core/injectionCore/InstancesHolder.cs b/StackInjector/Core/Core/InstancesHolder.cs similarity index 100% rename from StackInjector/Core/injectionCore/InstancesHolder.cs rename to StackInjector/Core/Core/InstancesHolder.cs diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index adf1914..c4681c1 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -50,7 +50,7 @@ public StackWrapperSettings Clone () => /// , /// /// - public static StackWrapperSettings Default => With(null, null, null); + public static StackWrapperSettings Default => With(); /// @@ -60,7 +60,7 @@ public StackWrapperSettings Clone () => /// the runtime options /// mask options /// - public static StackWrapperSettings With ( Injection injection, Runtime runtime, Mask mask ) + public static StackWrapperSettings With ( Injection injection = null, Runtime runtime = null, Mask mask = null ) => new StackWrapperSettings() { diff --git a/StackInjector/Settings/StackWrapperSettings.injection.cs b/StackInjector/Settings/StackWrapperSettings.injection.cs index 78d899b..8ec4122 100644 --- a/StackInjector/Settings/StackWrapperSettings.injection.cs +++ b/StackInjector/Settings/StackWrapperSettings.injection.cs @@ -105,10 +105,10 @@ public Injection ServingMethod ( ServingMethods methods, bool @override = false return this; } - + //todo this is never called in the code. check. /// /// Remove the reference to unused types after the injection is finished.
- /// Usually not necessay, but can save memory after cloning + /// Usually not necessay, but can save memory after cloning. ///
/// The modified settings public Injection RemoveUnusedTypesAfterInjection ( bool remove = true ) diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index ed8a7ed..10d2d78 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -46,9 +46,10 @@ internal class ClassInExternalAssemblyBase {[Served] public Externalclass extern [Test] public void ThrowsServiceNotFound () { - var settings = SWS.Default; - // add to blacklist - settings.MaskOptions.Register(typeof(Externalclass)); + var settings = SWS.With( + mask: SWS.Mask.BlackList + .Register(typeof(Externalclass)) + ); //todo change to specific mask exception Assert.Throws(() => Injector.From(settings)); From 423438d6c318cf1b2372abf8cd5b19732576f511 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Thu, 25 Feb 2021 22:57:42 +0100 Subject: [PATCH 11/26] fixed folder naming error. beatiful case insensitive windows folders. --- StackInjector/Core/{Core => InjectionCore}/InjectionCore.cs | 0 .../Core/{Core => InjectionCore}/InjectionCore.injection.cs | 0 .../Core/{Core => InjectionCore}/InjectionCore.instantiation.cs | 0 .../Core/{Core => InjectionCore}/InjectionCore.reflection.cs | 0 StackInjector/Core/{Core => InjectionCore}/InjectionCore.serve.cs | 0 .../Core/{Core => InjectionCore}/InjectionCore.utilities.cs | 0 .../Core/{Core => InjectionCore}/InjectionCore.versioning.cs | 0 StackInjector/Core/{Core => }/InstancesHolder.cs | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename StackInjector/Core/{Core => InjectionCore}/InjectionCore.cs (100%) rename StackInjector/Core/{Core => InjectionCore}/InjectionCore.injection.cs (100%) rename StackInjector/Core/{Core => InjectionCore}/InjectionCore.instantiation.cs (100%) rename StackInjector/Core/{Core => InjectionCore}/InjectionCore.reflection.cs (100%) rename StackInjector/Core/{Core => InjectionCore}/InjectionCore.serve.cs (100%) rename StackInjector/Core/{Core => InjectionCore}/InjectionCore.utilities.cs (100%) rename StackInjector/Core/{Core => InjectionCore}/InjectionCore.versioning.cs (100%) rename StackInjector/Core/{Core => }/InstancesHolder.cs (100%) diff --git a/StackInjector/Core/Core/InjectionCore.cs b/StackInjector/Core/InjectionCore/InjectionCore.cs similarity index 100% rename from StackInjector/Core/Core/InjectionCore.cs rename to StackInjector/Core/InjectionCore/InjectionCore.cs diff --git a/StackInjector/Core/Core/InjectionCore.injection.cs b/StackInjector/Core/InjectionCore/InjectionCore.injection.cs similarity index 100% rename from StackInjector/Core/Core/InjectionCore.injection.cs rename to StackInjector/Core/InjectionCore/InjectionCore.injection.cs diff --git a/StackInjector/Core/Core/InjectionCore.instantiation.cs b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs similarity index 100% rename from StackInjector/Core/Core/InjectionCore.instantiation.cs rename to StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs diff --git a/StackInjector/Core/Core/InjectionCore.reflection.cs b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs similarity index 100% rename from StackInjector/Core/Core/InjectionCore.reflection.cs rename to StackInjector/Core/InjectionCore/InjectionCore.reflection.cs diff --git a/StackInjector/Core/Core/InjectionCore.serve.cs b/StackInjector/Core/InjectionCore/InjectionCore.serve.cs similarity index 100% rename from StackInjector/Core/Core/InjectionCore.serve.cs rename to StackInjector/Core/InjectionCore/InjectionCore.serve.cs diff --git a/StackInjector/Core/Core/InjectionCore.utilities.cs b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs similarity index 100% rename from StackInjector/Core/Core/InjectionCore.utilities.cs rename to StackInjector/Core/InjectionCore/InjectionCore.utilities.cs diff --git a/StackInjector/Core/Core/InjectionCore.versioning.cs b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs similarity index 100% rename from StackInjector/Core/Core/InjectionCore.versioning.cs rename to StackInjector/Core/InjectionCore/InjectionCore.versioning.cs diff --git a/StackInjector/Core/Core/InstancesHolder.cs b/StackInjector/Core/InstancesHolder.cs similarity index 100% rename from StackInjector/Core/Core/InstancesHolder.cs rename to StackInjector/Core/InstancesHolder.cs From 444b83ae16df8fca29de26a15c2bed6ca1d834c1 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Thu, 25 Feb 2021 23:18:40 +0100 Subject: [PATCH 12/26] minor fixing. minor zombie code removal, added 2 new tests. --- StackInjector/Core/Cloning/ClonedCore.cs | 6 ------ StackInjector/Core/InstancesHolder.cs | 1 - .../StackWrapperSettings.injection.cs | 1 - .../Settings/StackWrapperSettings.mask.cs | 8 ++++++-- .../UseCases/Exceptions.cs | 19 ++++++++++++++++++- .../UseCases/Sync.cs | 2 -- 6 files changed, 24 insertions(+), 13 deletions(-) diff --git a/StackInjector/Core/Cloning/ClonedCore.cs b/StackInjector/Core/Cloning/ClonedCore.cs index 4c18fbc..998debb 100644 --- a/StackInjector/Core/Cloning/ClonedCore.cs +++ b/StackInjector/Core/Cloning/ClonedCore.cs @@ -20,9 +20,6 @@ public IAsyncStackWrapper ToAsyncWrapper ( }; this.clonedCore.EntryType = typeof(TEntry); - //todo check this - //if( this.clonedCore.settings.MaskOptions._registerAfterCloning ) - // this.clonedCore.ReadAssemblies(); this.clonedCore.Serve(cloned:true); return wrapper; @@ -33,9 +30,6 @@ public IStackWrapper ToWrapper () var wrapper = new StackWrapper(this.clonedCore); this.clonedCore.EntryType = typeof(T); - //todo check this - //if( this.clonedCore.settings.MaskOptions._registerAfterCloning ) - // this.clonedCore.ReadAssemblies(); this.clonedCore.Serve(cloned:true); return wrapper; diff --git a/StackInjector/Core/InstancesHolder.cs b/StackInjector/Core/InstancesHolder.cs index 521f92d..affa74d 100644 --- a/StackInjector/Core/InstancesHolder.cs +++ b/StackInjector/Core/InstancesHolder.cs @@ -34,7 +34,6 @@ internal void CountAllInstances () } - //todo review // clones just the structure, the classes references are not cloned internal InstancesHolder CloneStructure () { diff --git a/StackInjector/Settings/StackWrapperSettings.injection.cs b/StackInjector/Settings/StackWrapperSettings.injection.cs index 8ec4122..8b6e3fc 100644 --- a/StackInjector/Settings/StackWrapperSettings.injection.cs +++ b/StackInjector/Settings/StackWrapperSettings.injection.cs @@ -105,7 +105,6 @@ public Injection ServingMethod ( ServingMethods methods, bool @override = false return this; } - //todo this is never called in the code. check. /// /// Remove the reference to unused types after the injection is finished.
/// Usually not necessay, but can save memory after cloning. diff --git a/StackInjector/Settings/StackWrapperSettings.mask.cs b/StackInjector/Settings/StackWrapperSettings.mask.cs index 3a0d0fe..516045a 100644 --- a/StackInjector/Settings/StackWrapperSettings.mask.cs +++ b/StackInjector/Settings/StackWrapperSettings.mask.cs @@ -1,4 +1,6 @@ -using System; +#define CONTRACTS_ALL + +using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; @@ -33,7 +35,9 @@ private Mask () { } /// The modified Mask object public Mask Register ( params Type[] types ) { - Contract.Requires(!_isDisabled); //todo test preconditions + if ( _isDisabled ) + throw new InvalidOperationException("cannot register to a disabled mask"); + foreach ( var t in types ) base.Add(t); return this; diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index 10d2d78..f17d8f9 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -39,6 +39,15 @@ public void ThrowsBaseNotAService () // ---------- + [Service] + private abstract class AbstractThrower { } + + [Test] + public void ThrowsOnAbstractClass () + => Assert.Throws( () => Injector.From() ); + + // ---------- + // references class in unregistred external assembly [Service] internal class ClassInExternalAssemblyBase {[Served] public Externalclass externalClass; } @@ -167,7 +176,6 @@ public void NotThrowsInstLimitReach_Singleton () } // ---------- - [Test] [Timeout(500)] @@ -178,5 +186,14 @@ public void ThrowsInstLimitReach_Cloned () .LimitInstancesCount(1); Assert.Throws( () => Injector.From().CloneCore(settings).ToWrapper() ); } + + // ---------- + + + [Test] + public void ThrowsOnMaskDisabled () + => Assert.Throws( () => SWS.Mask.Disabled.Register() ); + + } } diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs index 38887d9..ca4106e 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs @@ -10,8 +10,6 @@ #pragma warning disable CS0649 namespace StackInjector.TEST.BlackBox.UseCases { - - //todo add test for abastract classes internal class Sync : CommonTestingMethods { From 4d431759f04d178760b68198553e034a55f4bbd4 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Thu, 25 Feb 2021 23:24:33 +0100 Subject: [PATCH 13/26] removed unused assemblies --- .../Core/InjectionCore/InjectionCore.reflection.cs | 2 -- StackInjector/Core/InstancesHolder.cs | 1 - StackInjector/Settings/DefaultConstants.cs | 1 - StackInjector/Settings/StackWrapperSettings.IOption.cs | 2 -- StackInjector/Settings/StackWrapperSettings.cs | 6 +----- StackInjector/Settings/StackWrapperSettings.injection.cs | 4 +--- StackInjector/Settings/StackWrapperSettings.mask.cs | 4 ---- StackInjector/Settings/StackWrapperSettings.runtime.cs | 6 +----- tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs | 4 ---- .../Features/Test.InstantiationDiff.cs | 1 - tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs | 4 ---- tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs | 1 - 12 files changed, 3 insertions(+), 33 deletions(-) diff --git a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs index 5dacd65..46780a5 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; -using System.Threading; using StackInjector.Attributes; using StackInjector.Exceptions; diff --git a/StackInjector/Core/InstancesHolder.cs b/StackInjector/Core/InstancesHolder.cs index affa74d..fae8df9 100644 --- a/StackInjector/Core/InstancesHolder.cs +++ b/StackInjector/Core/InstancesHolder.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; namespace StackInjector.Core diff --git a/StackInjector/Settings/DefaultConstants.cs b/StackInjector/Settings/DefaultConstants.cs index 17c947b..8513c33 100644 --- a/StackInjector/Settings/DefaultConstants.cs +++ b/StackInjector/Settings/DefaultConstants.cs @@ -1,5 +1,4 @@ using StackInjector.Attributes; -using StackInjector.Settings; namespace StackInjector.Settings { diff --git a/StackInjector/Settings/StackWrapperSettings.IOption.cs b/StackInjector/Settings/StackWrapperSettings.IOption.cs index f2d57ae..2a28606 100644 --- a/StackInjector/Settings/StackWrapperSettings.IOption.cs +++ b/StackInjector/Settings/StackWrapperSettings.IOption.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace StackInjector.Settings { diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index c4681c1..c0564ec 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using StackInjector.Wrappers; +using StackInjector.Wrappers; namespace StackInjector.Settings { diff --git a/StackInjector/Settings/StackWrapperSettings.injection.cs b/StackInjector/Settings/StackWrapperSettings.injection.cs index 8b6e3fc..e5d9cc9 100644 --- a/StackInjector/Settings/StackWrapperSettings.injection.cs +++ b/StackInjector/Settings/StackWrapperSettings.injection.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; +using System.Collections.Generic; namespace StackInjector.Settings { diff --git a/StackInjector/Settings/StackWrapperSettings.mask.cs b/StackInjector/Settings/StackWrapperSettings.mask.cs index 516045a..6a47ce8 100644 --- a/StackInjector/Settings/StackWrapperSettings.mask.cs +++ b/StackInjector/Settings/StackWrapperSettings.mask.cs @@ -2,10 +2,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Linq; -using System.Text; -using StackInjector.Exceptions; namespace StackInjector.Settings { diff --git a/StackInjector/Settings/StackWrapperSettings.runtime.cs b/StackInjector/Settings/StackWrapperSettings.runtime.cs index 2ded472..40f0fd8 100644 --- a/StackInjector/Settings/StackWrapperSettings.runtime.cs +++ b/StackInjector/Settings/StackWrapperSettings.runtime.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace StackInjector.Settings +namespace StackInjector.Settings { partial class StackWrapperSettings { diff --git a/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs b/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs index b590162..e638644 100644 --- a/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs +++ b/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using NUnit.Framework; -using NUnit.Framework.Interfaces; namespace StackInjector.TEST.BlackBox { diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs index e304afc..3c172c3 100644 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs +++ b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs @@ -1,5 +1,4 @@ using System.Linq; -using NuGet.Frameworks; using NUnit.Framework; using StackInjector.Attributes; using StackInjector.Exceptions; diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index f17d8f9..3966150 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -1,17 +1,13 @@ using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; using NUnit.Framework; -using NUnit.Framework.Interfaces; using NUnit.Framework.Internal; using StackInjector.Attributes; using StackInjector.Exceptions; using StackInjector.Settings; using StackInjector.TEST.ExternalAssembly; -using StackInjector.TEST; using SWS = StackInjector.Settings.StackWrapperSettings; -using System.Threading.Tasks; namespace StackInjector.TEST.BlackBox.UseCases { diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs index ca4106e..d72bd2d 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs @@ -5,7 +5,6 @@ using StackInjector.Core; using StackInjector.Exceptions; using StackInjector.Settings; -using StackInjector.TEST.ExternalAssembly; #pragma warning disable CS0649 namespace StackInjector.TEST.BlackBox.UseCases From 8878480d079af107f40c60062d70b979f566259d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Apr 2021 05:03:18 +0000 Subject: [PATCH 14/26] Bump Microsoft.NET.Test.Sdk in /tests/StackInjector.TEST.BlackBox Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 16.9.1 to 16.9.4. - [Release notes](https://github.com/microsoft/vstest/releases) - [Commits](https://github.com/microsoft/vstest/compare/v16.9.1...v16.9.4) 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 bb0fa6f..ad043e8 100644 --- a/tests/StackInjector.TEST.BlackBox/StackInjector.TEST.BlackBox.csproj +++ b/tests/StackInjector.TEST.BlackBox/StackInjector.TEST.BlackBox.csproj @@ -24,7 +24,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + From 6471b04b788423bd340c7df294373b0ccc436fdc Mon Sep 17 00:00:00 2001 From: Jacopo Date: Tue, 6 Apr 2021 16:38:06 +0200 Subject: [PATCH 15/26] refactored StackWrapperSettings options --- .../Core/AsyncStackWrapperCore.logic.cs | 4 +- .../Core/InjectionCore/InjectionCore.cs | 2 +- .../InjectionCore/InjectionCore.injection.cs | 6 +- .../InjectionCore.instantiation.cs | 2 +- .../InjectionCore/InjectionCore.reflection.cs | 4 +- .../Core/InjectionCore/InjectionCore.serve.cs | 6 +- .../InjectionCore/InjectionCore.utilities.cs | 4 +- .../InjectionCore/InjectionCore.versioning.cs | 4 +- StackInjector/Core/InstancesHolder.cs | 2 +- StackInjector/Injector.cs | 4 +- StackInjector/Settings/IOptions.cs | 22 +++ StackInjector/Settings/InjectionOptions.cs | 142 +++++++++++++++++ StackInjector/Settings/MaskOptions.cs | 78 ++++++++++ StackInjector/Settings/RuntimeOptions.cs | 54 +++++++ .../Settings/StackWrapperSettings.IOption.cs | 23 --- .../Settings/StackWrapperSettings.cs | 28 ++-- .../StackWrapperSettings.injection.cs | 147 ------------------ .../Settings/StackWrapperSettings.mask.cs | 80 ---------- .../StackWrapperSettings.registration.cs | 116 -------------- .../Settings/StackWrapperSettings.runtime.cs | 57 ------- .../Features/Test.InstantiationDiff.cs | 8 +- .../Features/Test.Versioning.cs | 6 +- .../UseCases/Exceptions.cs | 10 +- .../UseCases/Sync.cs | 4 +- 24 files changed, 344 insertions(+), 469 deletions(-) create mode 100644 StackInjector/Settings/IOptions.cs create mode 100644 StackInjector/Settings/InjectionOptions.cs create mode 100644 StackInjector/Settings/MaskOptions.cs create mode 100644 StackInjector/Settings/RuntimeOptions.cs delete mode 100644 StackInjector/Settings/StackWrapperSettings.IOption.cs delete mode 100644 StackInjector/Settings/StackWrapperSettings.injection.cs delete mode 100644 StackInjector/Settings/StackWrapperSettings.mask.cs delete mode 100644 StackInjector/Settings/StackWrapperSettings.registration.cs delete mode 100644 StackInjector/Settings/StackWrapperSettings.runtime.cs diff --git a/StackInjector/Core/AsyncStackWrapperCore.logic.cs b/StackInjector/Core/AsyncStackWrapperCore.logic.cs index 96b2c84..6b6e238 100644 --- a/StackInjector/Core/AsyncStackWrapperCore.logic.cs +++ b/StackInjector/Core/AsyncStackWrapperCore.logic.cs @@ -85,7 +85,7 @@ Task listAwaiter () return this._emptyListAwaiter.WaitAsync(); } - switch( this.Settings.RuntimeOptions._asyncWaitingMethod ) + switch( this.Settings.Runtime._asyncWaitingMethod ) { case AsyncWaitingMethod.Exit: @@ -103,7 +103,7 @@ Task listAwaiter () case AsyncWaitingMethod.Timeout: var list = listAwaiter(); - var timeout = Task.Delay( this.Settings.RuntimeOptions._asyncWaitTime ); + 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; diff --git a/StackInjector/Core/InjectionCore/InjectionCore.cs b/StackInjector/Core/InjectionCore/InjectionCore.cs index 0a013af..6904fd4 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.cs @@ -54,7 +54,7 @@ internal InjectionCore ( StackWrapperSettings settings ) this.instances = new InstancesHolder(); - if( this.settings.InjectionOptions._trackInstancesDiff ) + if( this.settings.Injection._trackInstancesDiff ) this.instancesDiff = new List(); } diff --git a/StackInjector/Core/InjectionCore/InjectionCore.injection.cs b/StackInjector/Core/InjectionCore/InjectionCore.injection.cs index 631f8cf..535f3c5 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.injection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.injection.cs @@ -23,8 +23,8 @@ private IEnumerable InjectServicesInto ( object instance ) // otherwise check if the type has a service attribute and // if its property has been defined. var serving = - (this.settings.InjectionOptions._overrideServingMethod || serviceAtt is null || !(serviceAtt._servingDefined)) - ? this.settings.InjectionOptions._servingMethod + (this.settings.Injection._overrideServingMethod || serviceAtt is null || !(serviceAtt._servingDefined)) + ? this.settings.Injection._servingMethod : serviceAtt.Serving; // don't waste time serving if not necessary @@ -105,7 +105,7 @@ ref used private object InstTypeOrServiceEnum ( Type type, ServedAttribute servedAttribute, ref List used ) { if ( - this.settings.InjectionOptions._serveEnumerables + this.settings.Injection._serveEnumerables && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>) ) diff --git a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs index 9430951..098032e 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs @@ -49,7 +49,7 @@ private object InstantiateService ( Type type ) this.instances.total_count++; // if true, track instantiated objects - if ( this.settings.InjectionOptions._trackInstancesDiff ) + if ( this.settings.Injection._trackInstancesDiff ) this.instancesDiff.Add(instance); return instance; diff --git a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs index 46780a5..fbb45c9 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs @@ -46,8 +46,8 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr void MaskPass (Type type) { - if ( this.settings.MaskOptions.IsMasked(type) ) - throw new Exception($"Type {type.Name} is { (this.settings.MaskOptions._isWhiteList ? "not whitelisted" : "blacklisted")}"); + if ( this.settings.Mask.IsMasked(type) ) + throw new Exception($"Type {type.Name} is { (this.settings.Mask._isWhiteList ? "not whitelisted" : "blacklisted")}"); //todo create custom exception } diff --git a/StackInjector/Core/InjectionCore/InjectionCore.serve.cs b/StackInjector/Core/InjectionCore/InjectionCore.serve.cs index c64d530..29ed529 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.serve.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.serve.cs @@ -49,16 +49,16 @@ internal void Serve ( bool cloned = false ) } // cleanup - if( this.settings.InjectionOptions._cleanUnusedTypesAftInj ) + if( this.settings.Injection._cleanUnusedTypesAftInj ) this.RemoveUnusedTypes(); void checkInstancesLimit () { - if ( this.instances.total_count > this.settings.InjectionOptions._limitInstancesCount ) + if ( this.instances.total_count > this.settings.Injection._limitInstancesCount ) throw new InstancesLimitReachedException( - $"Reached limit of {this.settings.InjectionOptions._limitInstancesCount} instances." + $"Reached limit of {this.settings.Injection._limitInstancesCount} instances." ); } } diff --git a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs index 06c51b2..2d5db7a 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs @@ -38,7 +38,7 @@ internal void RemoveUnusedTypes () // removes instances of the tracked instantiated types and call their Dispose method. Thread safe. protected internal void RemoveInstancesDiff () { - if( !this.settings.InjectionOptions._trackInstancesDiff ) + if( !this.settings.Injection._trackInstancesDiff ) return; // ensures that two threads are not trying to Dispose and InjectAll at the same time @@ -49,7 +49,7 @@ protected internal void RemoveInstancesDiff () this.instances[instance.GetType()].Remove(instance); // if the relative setting is true, check if the instance implements IDisposable and call it - if( this.settings.InjectionOptions._callDisposeOnInstanceDiff && instance is IDisposable disposable ) + if( this.settings.Injection._callDisposeOnInstanceDiff && instance is IDisposable disposable ) disposable.Dispose(); } diff --git a/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs index 10e3013..283cfc3 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.versioning.cs @@ -15,8 +15,8 @@ private IEnumerable Version ( Type targetType, ServedAttribute servedAttri var targetVersion = servedAttribute?.TargetVersion ?? 0.0; var method = - (this.settings.InjectionOptions._overrideTargetingMethod || servedAttribute is null || !(servedAttribute._targetingDefined)) - ? this.settings.InjectionOptions._targetingMethod + (this.settings.Injection._overrideTargetingMethod || servedAttribute is null || !(servedAttribute._targetingDefined)) + ? this.settings.Injection._targetingMethod : servedAttribute.TargetingMethod; diff --git a/StackInjector/Core/InstancesHolder.cs b/StackInjector/Core/InstancesHolder.cs index fae8df9..dd7f8e1 100644 --- a/StackInjector/Core/InstancesHolder.cs +++ b/StackInjector/Core/InstancesHolder.cs @@ -6,7 +6,7 @@ namespace StackInjector.Core { internal class InstancesHolder : Dictionary> { - internal uint total_count = 0; + internal uint total_count; // 0 internal IEnumerable TypesAssignableFrom ( Type type ) => this diff --git a/StackInjector/Injector.cs b/StackInjector/Injector.cs index 6ff43a0..9b343b0 100644 --- a/StackInjector/Injector.cs +++ b/StackInjector/Injector.cs @@ -1,8 +1,10 @@ -using StackInjector.Core; +using System; +using StackInjector.Core; using StackInjector.Exceptions; using StackInjector.Settings; using StackInjector.Wrappers; +[assembly:CLSCompliant(true)] namespace StackInjector { /// diff --git a/StackInjector/Settings/IOptions.cs b/StackInjector/Settings/IOptions.cs new file mode 100644 index 0000000..accbee6 --- /dev/null +++ b/StackInjector/Settings/IOptions.cs @@ -0,0 +1,22 @@ +using System; + +namespace StackInjector.Settings +{ + + /// + /// Base class for options.
+ /// Options groups are a class of settings grouped by function/scope of use. + ///
+ public interface IOptions : ICloneable + { + /// + /// Create a default instance of this options group valorized with default values.
+ /// Default values may differ from uninitialized ones. + ///
+ /// + protected internal IOptions CreateDefault (); + + } + + +} diff --git a/StackInjector/Settings/InjectionOptions.cs b/StackInjector/Settings/InjectionOptions.cs new file mode 100644 index 0000000..83139a0 --- /dev/null +++ b/StackInjector/Settings/InjectionOptions.cs @@ -0,0 +1,142 @@ +using System.Collections.Generic; + +namespace StackInjector.Settings +{ + + /// + /// Options for the injection process. + /// + public sealed class InjectionOptions : IOptions + { + internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; + internal bool _overrideTargetingMethod; + + internal ServingMethods _servingMethod = StackWrapperSettings.DefaultConstants.ServeAllStrict; + internal bool _overrideServingMethod; + internal bool _cleanUnusedTypesAftInj; + internal uint _limitInstancesCount = 128; + + internal bool _serveEnumerables = true; + + // disposing + internal bool _trackInstancesDiff; + internal bool _callDisposeOnInstanceDiff; + + + internal InjectionOptions () { } + + + IOptions IOptions.CreateDefault () => Default; + + /// + public object Clone () => MemberwiseClone(); + + + /// + /// The default injection. Settings are valorized as following: + /// + /// + /// + /// , false + /// + /// + /// , false + /// + /// + /// false + /// + /// + /// 128 + /// + /// + /// true + /// + /// + /// false, false + /// + /// + /// + public static InjectionOptions Default => new InjectionOptions(); + + + #region configuration methods + + + /// + /// Track every new instantiated class to be deleted upon Dispose. + /// + /// if true, track instances diff + /// if true, call Dispose on services implementing + /// the modified settings + public InjectionOptions TrackInstantiationDiff ( bool track = true, bool callDispose = true ) + { + this._trackInstancesDiff = track; + this._callDisposeOnInstanceDiff = callDispose; + 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 + /// + /// the new default serving method for all services + /// if true, serving methods for [Service] calsses are overridden with the specified one + /// the modified settings + public InjectionOptions ServingMethod ( ServingMethods methods, bool @override = false ) + { + this._servingMethod = methods; + this._overrideServingMethod = @override; + return this; + } + + /// + /// Remove the reference to unused types after the injection is finished.
+ /// Usually not necessay, but can save memory after cloning. + ///
+ /// The modified settings + public InjectionOptions RemoveUnusedTypesAfterInjection ( bool remove = true ) + { + this._cleanUnusedTypesAftInj = remove; + return this; + } + + /// + /// Limits the TOTAL number of instances.
+ /// You can use to remove this limit, altough it is suggest to use the lowest possible value. + ///
+ /// the limit of total instances + /// The modified settings + public InjectionOptions LimitInstancesCount ( uint count = 128 ) + { + this._limitInstancesCount = count; + return this; + } + + /// + /// Allows to be injected with a list of every service implementing T + /// + /// if true, serve + /// the modified settings + public InjectionOptions ServeIEnumerables ( bool serve = true ) + { + this._serveEnumerables = serve; + return this; + } + + + #endregion + } +} diff --git a/StackInjector/Settings/MaskOptions.cs b/StackInjector/Settings/MaskOptions.cs new file mode 100644 index 0000000..83ed66f --- /dev/null +++ b/StackInjector/Settings/MaskOptions.cs @@ -0,0 +1,78 @@ +#define CONTRACTS_ALL + +using System; +using System.Collections.Generic; + +namespace StackInjector.Settings +{ + + //todo seealso custom mask exception + /// + /// Used to filter Types from the injection proces. + /// When trying to inject masked Types an injection will be thrown.
+ /// Use to Add multiple types at once. + ///
+ public sealed class MaskOptions : HashSet, IOptions + { + internal bool _isDisabled; + internal bool _isWhiteList; + + private MaskOptions () { } + + IOptions IOptions.CreateDefault () => Disabled; + + + /// + /// Register multiple Types at once.
+ /// see also + ///
+ /// types to register + /// The modified Mask object + public MaskOptions Register ( params Type[] types ) + { + if ( _isDisabled ) + throw new InvalidOperationException("cannot register to a disabled mask"); + + foreach ( var t in types ) + base.Add(t); + return this; + } + + + /// + /// Based on the type of mask, if the type is masked_out/forbidden from injection.
+ /// ie: if A is registered and this is a blacklist, IsMasked(A) will return true. + ///
+ /// type to be checked + /// always false when disabled, true if is masked. + public bool IsMasked ( Type type ) + { + if ( _isDisabled ) + return false; + else + return this._isWhiteList ^ this.Contains(type); //.XOR + + } + + /// + public object Clone () => MemberwiseClone(); + + + /// + /// allow only registred types. + /// + public static MaskOptions WhiteList => new MaskOptions() { _isWhiteList = true }; + + /// + /// allow every type except the regisred ones. + /// + public static MaskOptions BlackList => new MaskOptions(); + + /// + /// allow everything, don't even check. + /// + public static MaskOptions Disabled => new MaskOptions() { _isDisabled = true }; + + + } +} diff --git a/StackInjector/Settings/RuntimeOptions.cs b/StackInjector/Settings/RuntimeOptions.cs new file mode 100644 index 0000000..227d15f --- /dev/null +++ b/StackInjector/Settings/RuntimeOptions.cs @@ -0,0 +1,54 @@ +namespace StackInjector.Settings +{ + /// + /// Options used at runtime + /// + public sealed class RuntimeOptions : IOptions + { + + // async management + internal AsyncWaitingMethod _asyncWaitingMethod = AsyncWaitingMethod.Exit; + internal int _asyncWaitTime = 500; + + + internal RuntimeOptions () { } + + + IOptions IOptions.CreateDefault () => Default; + + /// + public object Clone () => this.MemberwiseClone(); + + + /// + /// Default runtime options. Settings are valorized as following: + /// + /// + /// + /// , 500 + /// + /// + /// + public static RuntimeOptions Default => new RuntimeOptions(); + + + #region configuration methods + + /// + /// 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 + /// the modified settings + public RuntimeOptions WhenNoMoreTasks ( AsyncWaitingMethod waitingMethod, int waitTime ) + { + this._asyncWaitingMethod = waitingMethod; + this._asyncWaitTime = waitTime; + return this; + } + + #endregion + + } +} diff --git a/StackInjector/Settings/StackWrapperSettings.IOption.cs b/StackInjector/Settings/StackWrapperSettings.IOption.cs deleted file mode 100644 index 2a28606..0000000 --- a/StackInjector/Settings/StackWrapperSettings.IOption.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace StackInjector.Settings -{ - partial class StackWrapperSettings - { - /// - /// Base class for options.
- /// Options groups are a class of settings grouped by function/scope of use. - ///
- public interface IOption : ICloneable - { - /// - /// Create a default instance of this options group valorized with default values.
- /// Default values may differ from uninitialized ones. - ///
- /// - protected internal IOption CreateDefault (); - - } - - } -} diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index c0564ec..5bb7aff 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -10,17 +10,17 @@ public sealed partial class StackWrapperSettings /// /// manages masking options. /// - public Mask MaskOptions { get; private set; } + public MaskOptions Mask { get; private set; } /// /// manages injection options /// - public Injection InjectionOptions { get; private set; } + public InjectionOptions Injection { get; private set; } /// /// manages runtime options /// - public Runtime RuntimeOptions { get; private set; } + public RuntimeOptions Runtime { get; private set; } @@ -34,17 +34,17 @@ private StackWrapperSettings () { } /// a cloned settings object public StackWrapperSettings Clone () => With( - (Injection)this.InjectionOptions.Clone(), - (Runtime)this.RuntimeOptions.Clone(), - (Mask)this.MaskOptions.Clone() + (InjectionOptions)this.Injection.Clone(), + (RuntimeOptions)this.Runtime.Clone(), + (MaskOptions)this.Mask.Clone() ); /// /// The default settings. see - /// , - /// , - /// + /// , + /// , + /// /// public static StackWrapperSettings Default => With(); @@ -56,13 +56,13 @@ public StackWrapperSettings Clone () => /// the runtime options /// mask options /// - public static StackWrapperSettings With ( Injection injection = null, Runtime runtime = null, Mask mask = null ) + public static StackWrapperSettings With ( InjectionOptions injection = null, RuntimeOptions runtime = null, MaskOptions mask = null ) => new StackWrapperSettings() { - MaskOptions = mask ?? Mask.Disabled, - InjectionOptions = injection ?? Injection.Default, - RuntimeOptions = runtime ?? Runtime.Default + Mask = mask ?? MaskOptions.Disabled, + Injection = injection ?? InjectionOptions.Default, + Runtime = runtime ?? RuntimeOptions.Default }; @@ -74,7 +74,7 @@ public static StackWrapperSettings With ( Injection injection = null, Runtime ru public static StackWrapperSettings DefaultBySubtraction => With( injection: - Injection.Default + InjectionOptions.Default .ServingMethod(DefaultConstants.ServeAll, true), mask: null, diff --git a/StackInjector/Settings/StackWrapperSettings.injection.cs b/StackInjector/Settings/StackWrapperSettings.injection.cs deleted file mode 100644 index e5d9cc9..0000000 --- a/StackInjector/Settings/StackWrapperSettings.injection.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System.Collections.Generic; - -namespace StackInjector.Settings -{ - partial class StackWrapperSettings - { - /// - /// Options for the injection process. - /// - public sealed class Injection : IOption - { - internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; - internal bool _overrideTargetingMethod; - - internal ServingMethods _servingMethod = DefaultConstants.ServeAllStrict; - internal bool _overrideServingMethod; - internal bool _cleanUnusedTypesAftInj; - internal uint _limitInstancesCount = 128; - - internal bool _serveEnumerables = true; - - // disposing - internal bool _trackInstancesDiff; - internal bool _callDisposeOnInstanceDiff; - - - internal Injection () { } - - - IOption IOption.CreateDefault () => Default; - - /// - public object Clone () => MemberwiseClone(); - - - /// - /// The default injection. Settings are valorized as following: - /// - /// - /// - /// , false - /// - /// - /// , false - /// - /// - /// false - /// - /// - /// 128 - /// - /// - /// true - /// - /// - /// false, false - /// - /// - /// - public static Injection Default => new Injection(); - - - #region configuration methods - - - /// - /// Track every new instantiated class to be deleted upon Dispose. - /// - /// if true, track instances diff - /// if true, call Dispose on services implementing - /// the modified settings - public Injection TrackInstantiationDiff ( bool track = true, bool callDispose = true ) - { - this._trackInstancesDiff = track; - this._callDisposeOnInstanceDiff = callDispose; - 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 Injection VersioningMethod ( ServedVersionTargetingMethod targetMethod, bool @override = false ) - { - this._targetingMethod = targetMethod; - this._overrideTargetingMethod = @override; - return this; - } - - /// - /// Overrides default serving method - /// - /// the new default serving method for all services - /// if true, serving methods for [Service] calsses are overridden with the specified one - /// the modified settings - public Injection ServingMethod ( ServingMethods methods, bool @override = false ) - { - this._servingMethod = methods; - this._overrideServingMethod = @override; - return this; - } - - /// - /// Remove the reference to unused types after the injection is finished.
- /// Usually not necessay, but can save memory after cloning. - ///
- /// The modified settings - public Injection RemoveUnusedTypesAfterInjection ( bool remove = true ) - { - this._cleanUnusedTypesAftInj = remove; - return this; - } - - /// - /// Limits the TOTAL number of instances.
- /// You can use to remove this limit, altough it is suggest to use the lowest possible value. - ///
- /// the limit of total instances - /// The modified settings - public Injection LimitInstancesCount ( uint count = 128 ) - { - this._limitInstancesCount = count; - return this; - } - - /// - /// Allows to be injected with a list of every service implementing T - /// - /// if true, serve - /// the modified settings - public Injection ServeIEnumerables ( bool serve = true ) - { - this._serveEnumerables = serve; - return this; - } - - - #endregion - - - } - - } -} diff --git a/StackInjector/Settings/StackWrapperSettings.mask.cs b/StackInjector/Settings/StackWrapperSettings.mask.cs deleted file mode 100644 index 6a47ce8..0000000 --- a/StackInjector/Settings/StackWrapperSettings.mask.cs +++ /dev/null @@ -1,80 +0,0 @@ -#define CONTRACTS_ALL - -using System; -using System.Collections.Generic; - -namespace StackInjector.Settings -{ - partial class StackWrapperSettings - { - //todo seealso custom mask exception - /// - /// Used to filter Types from the injection proces. - /// When trying to inject masked Types an injection will be thrown.
- /// Use to Add multiple types at once. - ///
- public sealed class Mask : HashSet, IOption - { - internal bool _isDisabled; - internal bool _isWhiteList; - - private Mask () { } - - IOption IOption.CreateDefault () => Disabled; - - - /// - /// Register multiple Types at once.
- /// see also - ///
- /// types to register - /// The modified Mask object - public Mask Register ( params Type[] types ) - { - if ( _isDisabled ) - throw new InvalidOperationException("cannot register to a disabled mask"); - - foreach ( var t in types ) - base.Add(t); - return this; - } - - - /// - /// Based on the type of mask, if the type is masked_out/forbidden from injection.
- /// ie: if A is registered and this is a blacklist, IsMasked(A) will return true. - ///
- /// type to be checked - /// always false when disabled, true if is masked. - public bool IsMasked ( Type type ) - { - if ( _isDisabled ) - return false; - else - return this._isWhiteList ^ this.Contains(type); //.XOR - - } - - /// - public object Clone () => MemberwiseClone(); - - - /// - /// allow only registred types. - /// - public static Mask WhiteList => new Mask() { _isWhiteList = true }; - - /// - /// allow every type except the regisred ones. - /// - public static Mask BlackList => new Mask(); - - /// - /// allow everything, don't even check. - /// - public static Mask Disabled => new Mask() { _isDisabled = true }; - - - } - } -} diff --git a/StackInjector/Settings/StackWrapperSettings.registration.cs b/StackInjector/Settings/StackWrapperSettings.registration.cs deleted file mode 100644 index e96f906..0000000 --- a/StackInjector/Settings/StackWrapperSettings.registration.cs +++ /dev/null @@ -1,116 +0,0 @@ - -#if FEATURE_REGISTRATION - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Text.RegularExpressions; - -namespace StackInjector.Settings -{ - - partial class StackWrapperSettings - { - - public sealed class Registration - { - // registration - internal HashSet _registredAssemblies = new HashSet(); - internal bool _registerEntryPointAssembly = true; - internal bool _registerWrapperAsService = true; - internal bool _registerAfterCloning; - - public static Registration Default => new Registration(); - - internal Registration () { } - - - /// - /// Register an external assembly from wich you want classes to be laoded. - /// - /// - /// the modified settings - public Registration RegisterAssemblies ( params Assembly[] assemblies ) - { - if ( assemblies is null ) - throw new ArgumentNullException(nameof(assemblies)); - - foreach ( var assembly in assemblies ) - this._registredAssemblies.Add(assembly); - return this; - } - - /// - /// Automatically register all domain assemblies, filtering the specified ones.
- /// Warning: CPU expensive - ///
- /// a regex string used to filter unwanted matching assemblies - /// the modified settings - public Registration RegisterDomain ( string regexFilter = Injector.Defaults.AssemblyRegexFilter ) - { - this.RegisterAssemblies - ( - AppDomain.CurrentDomain - .GetAssemblies() - .Where(a => !Regex.IsMatch(a.FullName, regexFilter)) - .ToArray() - ); - - return this; - } - - /// - /// Register the assembly of the specified type. - /// Same as . - /// - /// - /// the modified settings - public Registration RegisterAssemblyOf () - { - this.RegisterAssemblies(typeof(T).Assembly); - return this; - } - - /// - /// Register the entry point assembly when starting. - /// If set, there is no need to specify the entry assembly in . - /// Default is true. - /// - /// the modified settings - public Registration RegisterEntryAssembly ( bool register = true ) - { - this._registerEntryPointAssembly = register; - return this; - } - - /// - /// Register the wrapper as a service, so it can be accessed in contained classes. - /// Default is true. - /// - /// the modified settings - public Registration RegisterWrapperAsService ( bool register = true ) - { - this._registerWrapperAsService = register; - return this; - } - - - /// - /// If set, when cloned the StackWrapper will re-scans all assemblies before the injection. - /// Used to update assemblies with new types. - /// - /// the modified settings - public Registration RegisterAfterCloning ( bool register = true ) - { - this._registerAfterCloning = register; - return this; - } - - } - - } -} - -#endif \ No newline at end of file diff --git a/StackInjector/Settings/StackWrapperSettings.runtime.cs b/StackInjector/Settings/StackWrapperSettings.runtime.cs deleted file mode 100644 index 40f0fd8..0000000 --- a/StackInjector/Settings/StackWrapperSettings.runtime.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace StackInjector.Settings -{ - partial class StackWrapperSettings - { - /// - /// Options used at runtime - /// - public sealed class Runtime : IOption - { - - // async management - internal AsyncWaitingMethod _asyncWaitingMethod = AsyncWaitingMethod.Exit; - internal int _asyncWaitTime = 500; - - - internal Runtime () { } - - - IOption IOption.CreateDefault () => Default; - - /// - public object Clone () => this.MemberwiseClone(); - - - /// - /// Default runtime options. Settings are valorized as following: - /// - /// - /// - /// , 500 - /// - /// - /// - public static Runtime Default => new Runtime(); - - - #region configuration methods - - /// - /// 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 - /// the modified settings - public Runtime WhenNoMoreTasks ( AsyncWaitingMethod waitingMethod, int waitTime ) - { - this._asyncWaitingMethod = waitingMethod; - this._asyncWaitTime = waitTime; - return this; - } - - #endregion - - } - } -} diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs index 3c172c3..fdbe761 100644 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs +++ b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs @@ -32,7 +32,7 @@ private class ServiceA public void SimpleClone () { var settings = StackWrapperSettings.Default; - settings.InjectionOptions + settings.Injection .TrackInstantiationDiff(); IStackWrapper wrapperA, wrapperB; @@ -59,7 +59,7 @@ public void SimpleClone () public void SimpleCloneWithDispose () { var settings = StackWrapperSettings.Default; - settings.InjectionOptions + settings.Injection .TrackInstantiationDiff(); IStackWrapper wrapperB; @@ -80,7 +80,7 @@ public void SimpleCloneWithDispose () public void DeepClone () { var settings = StackWrapperSettings.Default; - settings.InjectionOptions + settings.Injection .TrackInstantiationDiff(); IStackWrapper wrapperB; @@ -108,7 +108,7 @@ public void DeepClone () public void DeepCloneWithDispose () { var settings = StackWrapperSettings.Default; - settings.InjectionOptions + settings.Injection .TrackInstantiationDiff(); IStackWrapper wrapperB; diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs index 0bd25cc..8fafaa0 100644 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs +++ b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs @@ -14,7 +14,7 @@ internal class Versioning : CommonTestingMethods public void ServedVersioningClass () { var settings = StackWrapperSettings.Default; - settings.InjectionOptions + settings.Injection .VersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); var versionedService = Injector.From(settings).Entry.Level1_2; @@ -39,7 +39,7 @@ public void ServedVersioningInterface () public void SettingVersioningLatestMaj () { var settings = StackWrapperSettings.Default; - settings.InjectionOptions + settings.Injection .VersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); var versionedService = Injector.From( settings ).Entry.level1; @@ -52,7 +52,7 @@ public void SettingVersioningLatestMaj () public void SettingVersioningLatestMin () { var settings = StackWrapperSettings.Default; - settings.InjectionOptions + settings.Injection .VersioningMethod(ServedVersionTargetingMethod.LatestMinor,true); var versionedService = Injector.From( settings ).Entry.level1; diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index 3966150..60e8536 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -52,7 +52,7 @@ internal class ClassInExternalAssemblyBase {[Served] public Externalclass extern public void ThrowsServiceNotFound () { var settings = SWS.With( - mask: SWS.Mask.BlackList + mask: MaskOptions.BlackList .Register(typeof(Externalclass)) ); @@ -152,7 +152,7 @@ public void NotThrowsInstLimitReach_Singleton_wBase () ExecuteTest(100, () => { var settings = SWS.Default; - settings.InjectionOptions + settings.Injection .LimitInstancesCount(2); Assert.DoesNotThrow(() => Injector.From(settings)); }); @@ -166,7 +166,7 @@ public void NotThrowsInstLimitReach_Singleton () ExecuteTest(100, () => { var settings = SWS.Default; - settings.InjectionOptions.LimitInstancesCount(2); + settings.Injection.LimitInstancesCount(2); Assert.DoesNotThrow(() => Injector.From(settings)); }); } @@ -178,7 +178,7 @@ public void NotThrowsInstLimitReach_Singleton () public void ThrowsInstLimitReach_Cloned () { var settings = SWS.Default; - settings.InjectionOptions + settings.Injection .LimitInstancesCount(1); Assert.Throws( () => Injector.From().CloneCore(settings).ToWrapper() ); } @@ -188,7 +188,7 @@ public void ThrowsInstLimitReach_Cloned () [Test] public void ThrowsOnMaskDisabled () - => Assert.Throws( () => SWS.Mask.Disabled.Register() ); + => Assert.Throws( () => MaskOptions.Disabled.Register() ); } diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs index d72bd2d..3c57379 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs @@ -44,7 +44,7 @@ public void FromInterface () public void ServeStrict () { var settings = StackWrapperSettings.Default; - settings.InjectionOptions + settings.Injection .ServingMethod( StackWrapperSettings.DefaultConstants.ServeAllStrict, true ); var entry = Injector.From(settings).Entry; @@ -57,7 +57,7 @@ public void ServeStrict () public void RemoveUnusedTypes () { var settings = StackWrapperSettings.Default; - settings.InjectionOptions + settings.Injection .RemoveUnusedTypesAfterInjection(); var wrap1 = Injector.From( settings ); From 3edef876d0fd82d20f1aaafbb84b656c89a5c3f5 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Tue, 6 Apr 2021 17:11:12 +0200 Subject: [PATCH 16/26] fixed most warnings --- .github/workflows/dotnet.yml | 1 + .../InjectionCore/InjectionCore.injection.cs | 2 +- .../InjectionCore/InjectionCore.reflection.cs | 2 +- .../Exceptions/InvalidEntryTypeException.cs | 6 ++-- StackInjector/Settings/DefaultConstants.cs | 33 ------------------- StackInjector/Settings/InjectionOptions.cs | 19 ++++++----- StackInjector/Settings/ServingMethods.cs | 4 +-- .../Settings/StackWrapperSettings.costants.cs | 25 ++++++++++++++ .../Settings/StackWrapperSettings.cs | 3 +- StackInjector/Wrappers/AsyncStackWrapper.cs | 2 +- StackInjector/Wrappers/StackWrapper.cs | 2 +- .../UseCases/Exceptions.cs | 2 +- .../UseCases/Sync.cs | 2 +- 13 files changed, 51 insertions(+), 52 deletions(-) delete mode 100644 StackInjector/Settings/DefaultConstants.cs create mode 100644 StackInjector/Settings/StackWrapperSettings.costants.cs diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 90b9402..d8434c9 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -15,6 +15,7 @@ on: jobs: test: + if: ${{ !( github.event_name == 'push' && matrix.os == 'windows-latest' ) }} runs-on: ${{ matrix.os }} env: DOTNET_NOLOGO: true diff --git a/StackInjector/Core/InjectionCore/InjectionCore.injection.cs b/StackInjector/Core/InjectionCore/InjectionCore.injection.cs index 535f3c5..6687d7e 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.injection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.injection.cs @@ -28,7 +28,7 @@ private IEnumerable InjectServicesInto ( object instance ) : serviceAtt.Serving; // don't waste time serving if not necessary - if( serving == ServingMethods.DoNotServe ) + if( serving == ServingMethods.None ) return servicesUsed; // if false avoids going though the properties/fields list a second time to filter diff --git a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs index fbb45c9..42cd746 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs @@ -47,7 +47,7 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr void MaskPass (Type type) { if ( this.settings.Mask.IsMasked(type) ) - throw new Exception($"Type {type.Name} is { (this.settings.Mask._isWhiteList ? "not whitelisted" : "blacklisted")}"); + throw new InvalidOperationException($"Type {type.Name} is { (this.settings.Mask._isWhiteList ? "not whitelisted" : "blacklisted")}"); //todo create custom exception } diff --git a/StackInjector/Exceptions/InvalidEntryTypeException.cs b/StackInjector/Exceptions/InvalidEntryTypeException.cs index b2b6ef7..d20d654 100644 --- a/StackInjector/Exceptions/InvalidEntryTypeException.cs +++ b/StackInjector/Exceptions/InvalidEntryTypeException.cs @@ -9,10 +9,12 @@ public sealed class InvalidEntryTypeException : StackInjectorException { internal InvalidEntryTypeException () { } - internal InvalidEntryTypeException ( Type type, string message ) : base(type, message) { } - internal InvalidEntryTypeException ( string message ) : base(message) { } + internal InvalidEntryTypeException ( string message, Exception innerException ) : base(message, innerException) { } + + internal InvalidEntryTypeException ( Type type, string message ) : base(type, message) { } + internal InvalidEntryTypeException ( Type type, string message, Exception innerException ) : base(type, message, innerException) { } } diff --git a/StackInjector/Settings/DefaultConstants.cs b/StackInjector/Settings/DefaultConstants.cs deleted file mode 100644 index 8513c33..0000000 --- a/StackInjector/Settings/DefaultConstants.cs +++ /dev/null @@ -1,33 +0,0 @@ -using StackInjector.Attributes; - -namespace StackInjector.Settings -{ - public partial class StackWrapperSettings - { - /// - /// Static class for default settings. - /// - public static class DefaultConstants - { - // the const keyword allows usage in attributes - - /// - /// The default serving method - /// - public const ServingMethods ServeAllStrict = - ( ServingMethods.Fields | ServingMethods.Properties | ServingMethods.Strict); - - /// - /// Serve every field and property ignoring if they have the - /// - public const ServingMethods ServeAll = - ( ServingMethods.Fields | ServingMethods.Properties ); - - - /// - /// Default regex to filter system assemblies - /// - public const string AssemblyRegexFilter = "^(System)|(Microsoft)"; - } - } -} diff --git a/StackInjector/Settings/InjectionOptions.cs b/StackInjector/Settings/InjectionOptions.cs index 83139a0..4f068b5 100644 --- a/StackInjector/Settings/InjectionOptions.cs +++ b/StackInjector/Settings/InjectionOptions.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace StackInjector.Settings { @@ -11,10 +12,10 @@ public sealed class InjectionOptions : IOptions internal ServedVersionTargetingMethod _targetingMethod = ServedVersionTargetingMethod.None; internal bool _overrideTargetingMethod; - internal ServingMethods _servingMethod = StackWrapperSettings.DefaultConstants.ServeAllStrict; + internal ServingMethods _servingMethod = StackWrapperSettings.ServeAllStrict; internal bool _overrideServingMethod; internal bool _cleanUnusedTypesAftInj; - internal uint _limitInstancesCount = 128; + internal int _limitInstancesCount = 128; internal bool _serveEnumerables = true; @@ -40,12 +41,12 @@ internal InjectionOptions () { } /// , false /// /// - /// , false + /// , false /// /// /// false /// - /// + /// /// 128 /// /// @@ -115,12 +116,14 @@ public InjectionOptions RemoveUnusedTypesAfterInjection ( bool remove = true ) /// /// Limits the TOTAL number of instances.
- /// You can use to remove this limit, altough it is suggest to use the lowest possible value. + /// You can use to remove this limit, altough it is suggest to use the lowest possible value. ///
- /// the limit of total instances + /// the limit of total instances. must be >=1 /// The modified settings - public InjectionOptions LimitInstancesCount ( uint count = 128 ) + public InjectionOptions LimitInstancesCount ( int count = 128 ) { + if ( count < 1 ) + throw new ArgumentOutOfRangeException(nameof(count)); this._limitInstancesCount = count; return this; } diff --git a/StackInjector/Settings/ServingMethods.cs b/StackInjector/Settings/ServingMethods.cs index d4609dd..cae2773 100644 --- a/StackInjector/Settings/ServingMethods.cs +++ b/StackInjector/Settings/ServingMethods.cs @@ -10,9 +10,9 @@ namespace StackInjector.Settings public enum ServingMethods { /// - /// empty servicing method + /// empty servicing method. Do not serve, disabling injection for a particular class. /// - DoNotServe = 0, + None = 0, /// /// Serve only to those properties or fields marked with . diff --git a/StackInjector/Settings/StackWrapperSettings.costants.cs b/StackInjector/Settings/StackWrapperSettings.costants.cs new file mode 100644 index 0000000..897bd68 --- /dev/null +++ b/StackInjector/Settings/StackWrapperSettings.costants.cs @@ -0,0 +1,25 @@ +using StackInjector.Attributes; + +namespace StackInjector.Settings +{ + public partial class StackWrapperSettings + { + /// + /// The default serving method + /// + public const ServingMethods ServeAllStrict = + ( ServingMethods.Fields | ServingMethods.Properties | ServingMethods.Strict); + + /// + /// Serve every field and property ignoring if they have the + /// + public const ServingMethods ServeAll = + ( ServingMethods.Fields | ServingMethods.Properties ); + + + /// + /// Default regex to filter system assemblies + /// + public const string AssemblyRegexFilter = "^(System)|(Microsoft)"; + } +} diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 5bb7aff..7d6d953 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -7,6 +7,7 @@ namespace StackInjector.Settings /// public sealed partial class StackWrapperSettings { + /// /// manages masking options. /// @@ -75,7 +76,7 @@ public static StackWrapperSettings With ( InjectionOptions injection = null, Run With( injection: InjectionOptions.Default - .ServingMethod(DefaultConstants.ServeAll, true), + .ServingMethod(ServeAll, true), mask: null, runtime: diff --git a/StackInjector/Wrappers/AsyncStackWrapper.cs b/StackInjector/Wrappers/AsyncStackWrapper.cs index dfd0619..ea9e7d5 100644 --- a/StackInjector/Wrappers/AsyncStackWrapper.cs +++ b/StackInjector/Wrappers/AsyncStackWrapper.cs @@ -5,7 +5,7 @@ namespace StackInjector.Wrappers { - [Service(Version = 3.0, Serving = ServingMethods.DoNotServe)] + [Service(Version = 3.0, Serving = ServingMethods.None)] internal class AsyncStackWrapper : AsyncStackWrapperCore, IAsyncStackWrapper { diff --git a/StackInjector/Wrappers/StackWrapper.cs b/StackInjector/Wrappers/StackWrapper.cs index 07a84c0..aa17789 100644 --- a/StackInjector/Wrappers/StackWrapper.cs +++ b/StackInjector/Wrappers/StackWrapper.cs @@ -5,7 +5,7 @@ namespace StackInjector.Wrappers { - [Service(Version = 3.0, Serving = ServingMethods.DoNotServe)] + [Service(Version = 3.0, Serving = ServingMethods.None)] internal class StackWrapper : StackWrapperCore, IStackWrapper { diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index 60e8536..04958e4 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -57,7 +57,7 @@ public void ThrowsServiceNotFound () ); //todo change to specific mask exception - Assert.Throws(() => Injector.From(settings)); + Assert.Throws(() => Injector.From(settings)); } diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs index 3c57379..4966e39 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs @@ -45,7 +45,7 @@ public void ServeStrict () { var settings = StackWrapperSettings.Default; settings.Injection - .ServingMethod( StackWrapperSettings.DefaultConstants.ServeAllStrict, true ); + .ServingMethod( StackWrapperSettings.ServeAllStrict, true ); var entry = Injector.From(settings).Entry; From 40350a5af11d24df4ea74d7e88c5140e31b1d15e Mon Sep 17 00:00:00 2001 From: Jacopo Date: Tue, 6 Apr 2021 17:26:51 +0200 Subject: [PATCH 17/26] updated workflows --- .../{dotnet.yml => dotnet_pullr.yml} | 14 ++++---- .github/workflows/dotnet_push.yml | 34 +++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) rename .github/workflows/{dotnet.yml => dotnet_pullr.yml} (86%) create mode 100644 .github/workflows/dotnet_push.yml diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet_pullr.yml similarity index 86% rename from .github/workflows/dotnet.yml rename to .github/workflows/dotnet_pullr.yml index d8434c9..11988ee 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet_pullr.yml @@ -1,21 +1,21 @@ -name: .NET tests +name: .NET PR tests +# runs only on pull requests on: - push: - paths-ignore: - - '**.md' - - '**.txt' pull_request: branches: - 'master' - 'rel/**' - 'dev/**' + paths-ignore: + - '**.md' + - '**.txt' + - '**.png' jobs: - test: - if: ${{ !( github.event_name == 'push' && matrix.os == 'windows-latest' ) }} + prtest: runs-on: ${{ matrix.os }} env: DOTNET_NOLOGO: true diff --git a/.github/workflows/dotnet_push.yml b/.github/workflows/dotnet_push.yml new file mode 100644 index 0000000..b86cf66 --- /dev/null +++ b/.github/workflows/dotnet_push.yml @@ -0,0 +1,34 @@ +name: .NET tests + +# runs on every push on every branch +on: + push: + paths-ignore: + - '**.md' + - '**.txt' + + +jobs: + + test: + runs-on: 'ubuntu-latest' + env: + DOTNET_NOLOGO: true + + steps: + - uses: actions/checkout@v2 + + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '5.0.x' + + - name: Install dependencies + run: dotnet restore + + - name: Build + run: dotnet build --no-restore --configuration Release + + - name: Test + run: dotnet test --no-restore --configuration Release --logger "console;verbosity=detailed" + From 5b339ba5031d1aed7d052088a6c2867d357ebd92 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Fri, 9 Apr 2021 18:33:17 +0200 Subject: [PATCH 18/26] code cleanup - AsyncStackWrappers now use EventHandle instead of Action --- StackInjector/Core/AsyncStackWrapperCore.cs | 4 +-- .../Core/AsyncStackWrapperCore.logic.cs | 32 ++++++++--------- StackInjector/Core/Cloning/ClonedCore.cs | 4 +-- StackInjector/Core/IAsyncStackWrapperCore.cs | 13 ++++++- .../Core/InjectionCore/InjectionCore.cs | 4 +-- .../InjectionCore/InjectionCore.injection.cs | 18 +++++----- .../InjectionCore.instantiation.cs | 6 ++-- .../InjectionCore/InjectionCore.reflection.cs | 6 ++-- .../Core/InjectionCore/InjectionCore.serve.cs | 12 +++---- .../InjectionCore/InjectionCore.utilities.cs | 10 +++--- StackInjector/Core/InstancesHolder.cs | 34 ++++++++++--------- StackInjector/Injector.cs | 6 ++-- StackInjector/Settings/IOptions.cs | 4 +-- StackInjector/Settings/InjectionOptions.cs | 12 +++++-- StackInjector/Settings/MaskOptions.cs | 16 ++++++--- StackInjector/Settings/RuntimeOptions.cs | 12 +++++-- .../Settings/StackWrapperSettings.cs | 21 +++++++----- StackInjector/Wrappers/StackWrapper.cs | 2 +- 18 files changed, 124 insertions(+), 92 deletions(-) diff --git a/StackInjector/Core/AsyncStackWrapperCore.cs b/StackInjector/Core/AsyncStackWrapperCore.cs index 43d4a4d..a3921f0 100644 --- a/StackInjector/Core/AsyncStackWrapperCore.cs +++ b/StackInjector/Core/AsyncStackWrapperCore.cs @@ -8,7 +8,7 @@ namespace StackInjector.Core internal abstract partial class AsyncStackWrapperCore : StackWrapperCore, IAsyncStackWrapperCore { - public event Action OnElaborated; + public event EventHandler> OnElaborated; // used to cancel everything @@ -47,7 +47,7 @@ internal AsyncStackWrapperCore ( InjectionCore core, Type toRegister ) : base(co public override void Dispose () { - if( !this.disposedValue ) + if ( !this.disposedValue ) { // managed resources diff --git a/StackInjector/Core/AsyncStackWrapperCore.logic.cs b/StackInjector/Core/AsyncStackWrapperCore.logic.cs index 6b6e238..d4f2a7b 100644 --- a/StackInjector/Core/AsyncStackWrapperCore.logic.cs +++ b/StackInjector/Core/AsyncStackWrapperCore.logic.cs @@ -16,25 +16,25 @@ protected internal void ReleaseListAwaiter () internal void Submit ( Task work ) { - lock( this._listAccessLock ) + lock ( this._listAccessLock ) this.tasks.AddLast(work); // if the list was empty just an item ago, signal it's not anymore. // this limit avoids useless cross thread calls that would slow everything down. - if( this.tasks.Count == 1 ) + if ( this.tasks.Count == 1 ) this.ReleaseListAwaiter(); } public bool AnyTaskLeft () { - lock( this._listAccessLock ) + lock ( this._listAccessLock ) return this.tasks.Any(); } public bool AnyTaskCompleted () { - lock( this._listAccessLock ) + lock ( this._listAccessLock ) return this.tasks.Any(t => t.IsCompleted); } @@ -42,16 +42,14 @@ public async IAsyncEnumerable Elaborated () { this.EnsureExclusiveExecution(true); - while( !this.cancelPendingTasksSource.IsCancellationRequested ) + while ( !this.cancelPendingTasksSource.IsCancellationRequested ) { // avoid deadlocks - if( this.AnyTaskLeft() ) + if ( this.AnyTaskLeft() ) { var completed = await Task.WhenAny(this.tasks).ConfigureAwait(false); - - - lock( this._listAccessLock ) + lock ( this._listAccessLock ) this.tasks.Remove(completed); yield return completed.Result; @@ -59,20 +57,20 @@ public async IAsyncEnumerable Elaborated () } else { - if( await this.OnNoTasksLeft().ConfigureAwait(true) ) + if ( await this.OnNoTasksLeft().ConfigureAwait(true) ) break; } } - lock( this._listAccessLock ) + lock ( this._listAccessLock ) this._exclusiveExecution = false; } public async Task Elaborate () { - await foreach( var res in this.Elaborated() ) - this.OnElaborated?.Invoke(res); + await foreach ( var res in this.Elaborated() ) + this.OnElaborated?.Invoke(this, new AsyncElaboratedEventArgs(res)); } @@ -85,7 +83,7 @@ Task listAwaiter () return this._emptyListAwaiter.WaitAsync(); } - switch( this.Settings.Runtime._asyncWaitingMethod ) + switch ( this.Settings.Runtime._asyncWaitingMethod ) { case AsyncWaitingMethod.Exit: @@ -112,12 +110,12 @@ Task listAwaiter () private void EnsureExclusiveExecution ( bool set = false ) { - lock( this._listAccessLock ) // reused lock + lock ( this._listAccessLock ) // reused lock { - if( this._exclusiveExecution ) + if ( this._exclusiveExecution ) throw new InvalidOperationException(); - if( set ) + if ( set ) this._exclusiveExecution = set; } } diff --git a/StackInjector/Core/Cloning/ClonedCore.cs b/StackInjector/Core/Cloning/ClonedCore.cs index 998debb..2cab7c1 100644 --- a/StackInjector/Core/Cloning/ClonedCore.cs +++ b/StackInjector/Core/Cloning/ClonedCore.cs @@ -20,7 +20,7 @@ public IAsyncStackWrapper ToAsyncWrapper ( }; this.clonedCore.EntryType = typeof(TEntry); - this.clonedCore.Serve(cloned:true); + this.clonedCore.Serve(cloned: true); return wrapper; } @@ -30,7 +30,7 @@ public IStackWrapper ToWrapper () var wrapper = new StackWrapper(this.clonedCore); this.clonedCore.EntryType = typeof(T); - this.clonedCore.Serve(cloned:true); + this.clonedCore.Serve(cloned: true); return wrapper; } diff --git a/StackInjector/Core/IAsyncStackWrapperCore.cs b/StackInjector/Core/IAsyncStackWrapperCore.cs index 4bd55f7..15d8f1e 100644 --- a/StackInjector/Core/IAsyncStackWrapperCore.cs +++ b/StackInjector/Core/IAsyncStackWrapperCore.cs @@ -5,6 +5,17 @@ namespace StackInjector.Core { + + public class AsyncElaboratedEventArgs : EventArgs + { + public T Result { get; internal set; } + + public AsyncElaboratedEventArgs ( T result ) + { + this.Result = result; + } + } + /// /// Base interface for all asyncronous stackwrappers. /// @@ -14,7 +25,7 @@ public interface IAsyncStackWrapperCore : IStackWrapperCore /// /// called when a new element has been elaborated /// - event Action OnElaborated; + event EventHandler> OnElaborated; /// diff --git a/StackInjector/Core/InjectionCore/InjectionCore.cs b/StackInjector/Core/InjectionCore/InjectionCore.cs index 6904fd4..dc2929b 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.cs @@ -22,7 +22,7 @@ internal Type EntryType set { var serviceAtt = value.GetCustomAttribute(); - if( serviceAtt != null && serviceAtt.Pattern == InstantiationPattern.AlwaysCreate ) + if ( serviceAtt != null && serviceAtt.Pattern == InstantiationPattern.AlwaysCreate ) throw new InvalidEntryTypeException( value, $"Entry point {value.Name} cannot have {InstantiationPattern.AlwaysCreate} as instantiation pattern.", @@ -54,7 +54,7 @@ internal InjectionCore ( StackWrapperSettings settings ) this.instances = new InstancesHolder(); - if( this.settings.Injection._trackInstancesDiff ) + if ( this.settings.Injection._trackInstancesDiff ) this.instancesDiff = new List(); } diff --git a/StackInjector/Core/InjectionCore/InjectionCore.injection.cs b/StackInjector/Core/InjectionCore/InjectionCore.injection.cs index 6687d7e..307fda8 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.injection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.injection.cs @@ -28,18 +28,18 @@ private IEnumerable InjectServicesInto ( object instance ) : serviceAtt.Serving; // don't waste time serving if not necessary - if( serving == ServingMethods.None ) + if ( serving == ServingMethods.None ) return servicesUsed; // if false avoids going though the properties/fields list a second time to filter var strict = serving.HasFlag(ServingMethods.Strict); - if( serving.HasFlag(ServingMethods.Fields) ) + if ( serving.HasFlag(ServingMethods.Fields) ) this.InjectFields(type, instance, ref servicesUsed, strict); - if( serving.HasFlag(ServingMethods.Properties) ) + if ( serving.HasFlag(ServingMethods.Properties) ) this.InjectProperties(type, instance, ref servicesUsed, strict); @@ -56,10 +56,10 @@ private void InjectFields ( Type type, object instance, ref List used, b type.GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ) .Where( f => f.GetCustomAttribute() is null ); - if( strict ) + if ( strict ) fields = fields.Where(field => field.GetCustomAttribute() != null); - foreach( var serviceField in fields ) + foreach ( var serviceField in fields ) { var serviceInstance = this.InstTypeOrServiceEnum @@ -80,12 +80,12 @@ private void InjectProperties ( Type type, object instance, ref List use type.GetProperties( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ) .Where( p => p.GetCustomAttribute() is null ); - if( strict ) + if ( strict ) properties = properties.Where(property => property.GetCustomAttribute() != null); - foreach( var serviceProperty in properties ) + foreach ( var serviceProperty in properties ) { - if( serviceProperty.GetSetMethod() is null ) + if ( serviceProperty.GetSetMethod() is null ) throw new NoSetterException(type, $"Property {serviceProperty.Name} of {type.FullName} has no setter!"); var serviceInstance = @@ -121,7 +121,7 @@ private object InstTypeOrServiceEnum ( Type type, ServedAttribute servedAttribut var instances = (IList)Activator.CreateInstance( listType ); // gather instances if necessary - foreach( var serviceType in validTypes ) + foreach ( var serviceType in validTypes ) { var obj = this.OfTypeOrInstantiate(serviceType); instances.Add(obj); diff --git a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs index 098032e..415b1d8 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs @@ -14,7 +14,7 @@ private object OfTypeOrInstantiate ( Type type ) var serviceAtt = type.GetCustomAttribute(); // manage exceptions - if( serviceAtt == null ) + if ( serviceAtt == null ) throw new NotAServiceException(type, $"Type {type.FullName} is not a [Service]"); ////if( !this.instances.ContainsKey(type) ) @@ -23,9 +23,9 @@ private object OfTypeOrInstantiate ( Type type ) return serviceAtt.Pattern switch { - InstantiationPattern.AlwaysCreate + InstantiationPattern.AlwaysCreate => this.InstantiateService(type), - _ + _ => (this.instances.ContainsKey(type) && this.instances[type].Any()) ? this.instances[type].First() : this.InstantiateService(type), diff --git a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs index 42cd746..60a6eb5 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.reflection.cs @@ -12,7 +12,7 @@ internal partial class InjectionCore // otherwise searches for a [Service] implementing the specified interface private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttribute = null ) { - if( type.IsInterface ) + if ( type.IsInterface ) { IEnumerable versions = this.instances.TypesAssignableFrom(type); @@ -44,13 +44,13 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr } - void MaskPass (Type type) + void MaskPass ( Type type ) { if ( this.settings.Mask.IsMasked(type) ) 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.serve.cs b/StackInjector/Core/InjectionCore/InjectionCore.serve.cs index 29ed529..c77b678 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.serve.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.serve.cs @@ -15,10 +15,10 @@ internal void Serve ( bool cloned = false ) if ( cloned ) this.instances.CountAllInstances(); - + // ensures that two threads are not trying to Dispose/InjectAll at the same time - lock( this._lock ) + lock ( this._lock ) { // EntryType must be a class this.EntryType = this.ClassOrVersionFromInterface(this.EntryType); @@ -28,7 +28,7 @@ internal void Serve ( bool cloned = false ) checkInstancesLimit(); // enqueuing loop - while( toInject.Any() ) + while ( toInject.Any() ) { var next = toInject.Dequeue(); var usedServices = this.InjectServicesInto(next); @@ -38,8 +38,8 @@ internal void Serve ( bool cloned = false ) // foreach injected object check if it has already been injected. // saves time in most situations - foreach( var service in usedServices ) - { + foreach ( var service in usedServices ) + { if ( !injected.Contains(service) ) { toInject.Enqueue(service); @@ -49,7 +49,7 @@ internal void Serve ( bool cloned = false ) } // cleanup - if( this.settings.Injection._cleanUnusedTypesAftInj ) + if ( this.settings.Injection._cleanUnusedTypesAftInj ) this.RemoveUnusedTypes(); diff --git a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs index 2d5db7a..5c87a7d 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs @@ -30,7 +30,7 @@ internal void RemoveUnusedTypes () .Select(p=>p.Key) .ToList(); - foreach( var type in unused ) + foreach ( var type in unused ) this.instances.Remove(type); } @@ -38,18 +38,18 @@ internal void RemoveUnusedTypes () // removes instances of the tracked instantiated types and call their Dispose method. Thread safe. protected internal void RemoveInstancesDiff () { - if( !this.settings.Injection._trackInstancesDiff ) + if ( !this.settings.Injection._trackInstancesDiff ) return; // ensures that two threads are not trying to Dispose and InjectAll at the same time - lock( this._lock ) + lock ( this._lock ) { - foreach( var instance in this.instancesDiff ) + foreach ( var instance in this.instancesDiff ) { this.instances[instance.GetType()].Remove(instance); // if the relative setting is true, check if the instance implements IDisposable and call it - if( this.settings.Injection._callDisposeOnInstanceDiff && instance is IDisposable disposable ) + if ( this.settings.Injection._callDisposeOnInstanceDiff && instance is IDisposable disposable ) disposable.Dispose(); } diff --git a/StackInjector/Core/InstancesHolder.cs b/StackInjector/Core/InstancesHolder.cs index dd7f8e1..89e41c4 100644 --- a/StackInjector/Core/InstancesHolder.cs +++ b/StackInjector/Core/InstancesHolder.cs @@ -8,27 +8,29 @@ internal class InstancesHolder : Dictionary> { internal uint total_count; // 0 - internal IEnumerable TypesAssignableFrom ( Type type ) => - this - .Keys - .Where(t => type.IsAssignableFrom(t)); - - - internal IEnumerable InstancesAssignableFrom ( Type type ) => - this - .Where(pair => type.IsAssignableFrom(pair.Key) && pair.Value.Any()) - .SelectMany(pair => pair.Value); - + internal IEnumerable TypesAssignableFrom ( Type type ) + { + return this + .Keys + .Where(t => type.IsAssignableFrom(t)); + } - internal bool AddType ( Type type ) => - this.TryAdd(type, new LinkedList() ); - + internal IEnumerable InstancesAssignableFrom ( Type type ) + { + return this + .Where(pair => type.IsAssignableFrom(pair.Key) && pair.Value.Any()) + .SelectMany(pair => pair.Value); + } + internal bool AddType ( Type type ) + { + return this.TryAdd(type, new LinkedList()); + } internal void CountAllInstances () { this.total_count = 0; - foreach (var pair in this) + foreach ( var pair in this ) this.total_count += (uint)pair.Value.Count; } @@ -38,7 +40,7 @@ internal InstancesHolder CloneStructure () { var clonedHolder = new InstancesHolder(); - foreach( var t in this.Keys ) + foreach ( var t in this.Keys ) clonedHolder.AddType(t); return clonedHolder; diff --git a/StackInjector/Injector.cs b/StackInjector/Injector.cs index 9b343b0..e9aee48 100644 --- a/StackInjector/Injector.cs +++ b/StackInjector/Injector.cs @@ -4,7 +4,7 @@ using StackInjector.Settings; using StackInjector.Wrappers; -[assembly:CLSCompliant(true)] +[assembly: CLSCompliant(true)] namespace StackInjector { /// @@ -30,7 +30,7 @@ public static partial class Injector /// public static IStackWrapper From ( StackWrapperSettings settings = null ) { - if( settings == null ) + if ( settings == null ) settings = StackWrapperSettings.Default; // create the core and wrap it @@ -73,7 +73,7 @@ public static IAsyncStackWrapper AsyncFrom StackWrapperSettings settings = null ) { - if( settings == null ) + if ( settings == null ) settings = StackWrapperSettings.Default; // create the core and wrap it diff --git a/StackInjector/Settings/IOptions.cs b/StackInjector/Settings/IOptions.cs index accbee6..0fb2f0a 100644 --- a/StackInjector/Settings/IOptions.cs +++ b/StackInjector/Settings/IOptions.cs @@ -15,8 +15,8 @@ public interface IOptions : ICloneable /// /// protected internal IOptions CreateDefault (); - + } - + } diff --git a/StackInjector/Settings/InjectionOptions.cs b/StackInjector/Settings/InjectionOptions.cs index 4f068b5..da3bd26 100644 --- a/StackInjector/Settings/InjectionOptions.cs +++ b/StackInjector/Settings/InjectionOptions.cs @@ -17,7 +17,7 @@ public sealed class InjectionOptions : IOptions internal bool _cleanUnusedTypesAftInj; internal int _limitInstancesCount = 128; - internal bool _serveEnumerables = true; + internal bool _serveEnumerables = true; // disposing internal bool _trackInstancesDiff; @@ -27,10 +27,16 @@ public sealed class InjectionOptions : IOptions internal InjectionOptions () { } - IOptions IOptions.CreateDefault () => Default; + IOptions IOptions.CreateDefault () + { + return Default; + } /// - public object Clone () => MemberwiseClone(); + public object Clone () + { + return MemberwiseClone(); + } /// diff --git a/StackInjector/Settings/MaskOptions.cs b/StackInjector/Settings/MaskOptions.cs index 83ed66f..e55ea41 100644 --- a/StackInjector/Settings/MaskOptions.cs +++ b/StackInjector/Settings/MaskOptions.cs @@ -19,7 +19,10 @@ public sealed class MaskOptions : HashSet, IOptions private MaskOptions () { } - IOptions IOptions.CreateDefault () => Disabled; + IOptions IOptions.CreateDefault () + { + return Disabled; + } /// @@ -55,23 +58,26 @@ public bool IsMasked ( Type type ) } /// - public object Clone () => MemberwiseClone(); + public object Clone () + { + return MemberwiseClone(); + } /// /// allow only registred types. /// - public static MaskOptions WhiteList => new MaskOptions() { _isWhiteList = true }; + public static MaskOptions WhiteList => new MaskOptions() { _isWhiteList = true }; /// /// allow every type except the regisred ones. /// - public static MaskOptions BlackList => new MaskOptions(); + public static MaskOptions BlackList => new MaskOptions(); /// /// allow everything, don't even check. /// - public static MaskOptions Disabled => new MaskOptions() { _isDisabled = true }; + public static MaskOptions Disabled => new MaskOptions() { _isDisabled = true }; } diff --git a/StackInjector/Settings/RuntimeOptions.cs b/StackInjector/Settings/RuntimeOptions.cs index 227d15f..3b53477 100644 --- a/StackInjector/Settings/RuntimeOptions.cs +++ b/StackInjector/Settings/RuntimeOptions.cs @@ -14,10 +14,16 @@ public sealed class RuntimeOptions : IOptions internal RuntimeOptions () { } - IOptions IOptions.CreateDefault () => Default; + IOptions IOptions.CreateDefault () + { + return Default; + } /// - public object Clone () => this.MemberwiseClone(); + public object Clone () + { + return this.MemberwiseClone(); + } /// @@ -50,5 +56,5 @@ public RuntimeOptions WhenNoMoreTasks ( AsyncWaitingMethod waitingMethod, int wa #endregion - } + } } diff --git a/StackInjector/Settings/StackWrapperSettings.cs b/StackInjector/Settings/StackWrapperSettings.cs index 7d6d953..25c7b79 100644 --- a/StackInjector/Settings/StackWrapperSettings.cs +++ b/StackInjector/Settings/StackWrapperSettings.cs @@ -33,12 +33,14 @@ private StackWrapperSettings () { } /// creates a deep copy of this settings object /// /// a cloned settings object - public StackWrapperSettings Clone () => - With( + public StackWrapperSettings Clone () + { + return With( (InjectionOptions)this.Injection.Clone(), (RuntimeOptions)this.Runtime.Clone(), (MaskOptions)this.Mask.Clone() ); + } /// @@ -49,7 +51,7 @@ public StackWrapperSettings Clone () => /// public static StackWrapperSettings Default => With(); - + /// /// create a new with the specified options. /// @@ -58,13 +60,14 @@ public StackWrapperSettings Clone () => /// mask options /// public static StackWrapperSettings With ( InjectionOptions injection = null, RuntimeOptions runtime = null, MaskOptions mask = null ) - => - new StackWrapperSettings() + { + return new StackWrapperSettings() { Mask = mask ?? MaskOptions.Disabled, Injection = injection ?? InjectionOptions.Default, Runtime = runtime ?? RuntimeOptions.Default }; + } /// @@ -72,14 +75,14 @@ public static StackWrapperSettings With ( InjectionOptions injection = null, Run /// everything is served by default, and you must instead use [Ignored] on properties and fields you don't want injected /// /// - public static StackWrapperSettings DefaultBySubtraction => + public static StackWrapperSettings DefaultBySubtraction => With( - injection: + injection: InjectionOptions.Default .ServingMethod(ServeAll, true), - mask: + mask: null, - runtime: + runtime: null ); diff --git a/StackInjector/Wrappers/StackWrapper.cs b/StackInjector/Wrappers/StackWrapper.cs index aa17789..0817566 100644 --- a/StackInjector/Wrappers/StackWrapper.cs +++ b/StackInjector/Wrappers/StackWrapper.cs @@ -38,7 +38,7 @@ public override string ToString () public override void Dispose () { - if( !this.disposed ) + if ( !this.disposed ) { this.Core.RemoveInstancesDiff(); From b8858bfb086a4c9f6d7a6982437fd0a65c75e824 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Fri, 9 Apr 2021 20:09:09 +0200 Subject: [PATCH 19/26] reviewed tests - add `StackWrapper.CountServices()` - killed some code zombies --- StackInjector/Core/IAsyncStackWrapperCore.cs | 12 +++-- StackInjector/Core/IStackWrapperCore.cs | 9 +++- .../InjectionCore/InjectionCore.utilities.cs | 2 + StackInjector/Core/InstancesHolder.cs | 4 +- StackInjector/Core/StackWrapperCore.cs | 10 ++-- StackInjector/Injector.cs | 2 - StackInjector/Settings/InjectionOptions.cs | 2 +- StackInjector/Wrappers/AsyncStackWrapper.cs | 9 +--- .../CommonTestingMethods.cs | 14 ------ .../SimpleStructure.cs | 2 +- .../UseCases/Async.cs | 46 ++++++++++++++----- .../UseCases/Exceptions.cs | 14 ------ .../UseCases/Sync.cs | 44 ++++++++---------- 13 files changed, 83 insertions(+), 87 deletions(-) diff --git a/StackInjector/Core/IAsyncStackWrapperCore.cs b/StackInjector/Core/IAsyncStackWrapperCore.cs index 15d8f1e..8c74d00 100644 --- a/StackInjector/Core/IAsyncStackWrapperCore.cs +++ b/StackInjector/Core/IAsyncStackWrapperCore.cs @@ -5,12 +5,18 @@ namespace StackInjector.Core { - - public class AsyncElaboratedEventArgs : EventArgs + /// + /// The event arguments for + /// + /// The generic returned type of the wrapper + public sealed class AsyncElaboratedEventArgs : EventArgs { + /// + /// Result of the elaboration + /// public T Result { get; internal set; } - public AsyncElaboratedEventArgs ( T result ) + internal AsyncElaboratedEventArgs ( T result ) { this.Result = result; } diff --git a/StackInjector/Core/IStackWrapperCore.cs b/StackInjector/Core/IStackWrapperCore.cs index 96e754a..a099879 100644 --- a/StackInjector/Core/IStackWrapperCore.cs +++ b/StackInjector/Core/IStackWrapperCore.cs @@ -22,8 +22,15 @@ public interface IStackWrapperCore : IDisposable, ICloneableCore /// Find every service valid for the given class or interface. /// /// - /// IEnumerable GetServices (); + + /// + /// The current number of all tracked services.
+ /// Does also include the Wrapper, so if you want all the instances + /// wrapper.CountServices()-1 + ///
+ int CountServices (); + } } \ No newline at end of file diff --git a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs index 5c87a7d..3e2af51 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.utilities.cs @@ -32,6 +32,8 @@ internal void RemoveUnusedTypes () foreach ( var type in unused ) this.instances.Remove(type); + + this.instances.CountAllInstances(); } diff --git a/StackInjector/Core/InstancesHolder.cs b/StackInjector/Core/InstancesHolder.cs index 89e41c4..f3114df 100644 --- a/StackInjector/Core/InstancesHolder.cs +++ b/StackInjector/Core/InstancesHolder.cs @@ -6,7 +6,7 @@ namespace StackInjector.Core { internal class InstancesHolder : Dictionary> { - internal uint total_count; // 0 + internal int total_count; // 0 internal IEnumerable TypesAssignableFrom ( Type type ) { @@ -31,7 +31,7 @@ internal void CountAllInstances () { this.total_count = 0; foreach ( var pair in this ) - this.total_count += (uint)pair.Value.Count; + this.total_count += pair.Value.Count; } diff --git a/StackInjector/Core/StackWrapperCore.cs b/StackInjector/Core/StackWrapperCore.cs index bab3a1a..2071ccd 100644 --- a/StackInjector/Core/StackWrapperCore.cs +++ b/StackInjector/Core/StackWrapperCore.cs @@ -22,13 +22,11 @@ public StackWrapperCore ( InjectionCore core, Type toRegister ) { this.Core = core; - //x setting for referencing the calling wrapper as a service - //x if( this.Core.settings.MaskOptions._registerWrapperAsService ) - + // add this wrapper to possible instances if ( !this.Core.instances.AddType(toRegister) ) this.Core.instances[toRegister].Clear(); this.Core.instances[toRegister].AddFirst(this); - + } @@ -40,6 +38,9 @@ public IEnumerable GetServices () .Select(o => (T)o); } + public int CountServices () => this.Core.instances.total_count; + + public IClonedCore CloneCore ( StackWrapperSettings settings = null ) { var clonedCore = new InjectionCore( settings ?? this.Core.settings ) @@ -62,6 +63,5 @@ public IClonedCore DeepCloneCore ( StackWrapperSettings settings = null ) public abstract void Dispose (); - } } diff --git a/StackInjector/Injector.cs b/StackInjector/Injector.cs index e9aee48..3470d28 100644 --- a/StackInjector/Injector.cs +++ b/StackInjector/Injector.cs @@ -42,7 +42,6 @@ public static IStackWrapper From ( StackWrapperSettings settings = null ) var wrapper = new StackWrapper(core); // initialize the injection process - ////core.ReadAssemblies(); core.Serve(); @@ -88,7 +87,6 @@ public static IAsyncStackWrapper AsyncFrom }; // initialize the injection process - ////core.ReadAssemblies(); core.Serve(); return wrapper; diff --git a/StackInjector/Settings/InjectionOptions.cs b/StackInjector/Settings/InjectionOptions.cs index da3bd26..7279921 100644 --- a/StackInjector/Settings/InjectionOptions.cs +++ b/StackInjector/Settings/InjectionOptions.cs @@ -15,7 +15,7 @@ public sealed class InjectionOptions : IOptions internal ServingMethods _servingMethod = StackWrapperSettings.ServeAllStrict; internal bool _overrideServingMethod; internal bool _cleanUnusedTypesAftInj; - internal int _limitInstancesCount = 128; + internal int _limitInstancesCount = 128; internal bool _serveEnumerables = true; diff --git a/StackInjector/Wrappers/AsyncStackWrapper.cs b/StackInjector/Wrappers/AsyncStackWrapper.cs index ea9e7d5..e4f7111 100644 --- a/StackInjector/Wrappers/AsyncStackWrapper.cs +++ b/StackInjector/Wrappers/AsyncStackWrapper.cs @@ -21,14 +21,7 @@ public AsyncStackWrapper ( InjectionCore core ) : base(core, typeof(AsyncStackWr public void Submit ( TIn item ) { - var task = this.StackDigest.Invoke - ( - this.Entry, - item, - this.PendingTasksCancellationToken - ); - - base.Submit(task); + this.SubmitAndGet(item); } public Task SubmitAndGet ( TIn item ) diff --git a/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs b/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs index e638644..46c2270 100644 --- a/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs +++ b/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs @@ -25,19 +25,5 @@ protected static void ExecuteTest ( int timeout, Action test ) Assert.Fail(ex.Message); } } - -////#if RELEASE -//// [TearDown] -//// public void ConsoleLogOnError () -//// { -//// var result = TestContext.CurrentContext.Result.Outcome.Status; -//// if ( result == TestStatus.Failed || result == TestStatus.Inconclusive ) -//// { -//// Console.WriteLine( -//// $"\t\tFailed:{TestContext.CurrentContext.Test.FullName}\n\t\tMessage:{TestContext.CurrentContext.Result.Message}" -//// ); -//// } -//// } -////#endif } } diff --git a/tests/StackInjector.TEST.BlackBox/SimpleStructure.cs b/tests/StackInjector.TEST.BlackBox/SimpleStructure.cs index 5114e49..1dcea14 100644 --- a/tests/StackInjector.TEST.BlackBox/SimpleStructure.cs +++ b/tests/StackInjector.TEST.BlackBox/SimpleStructure.cs @@ -61,7 +61,7 @@ internal class ForgotTheServedAttributeBase internal class AccessWrapperBase { [Served] - public ICloneableCore wrapper; + public IStackWrapperCore wrapper; public IStackWrapperCore Clone () => diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs index 375938e..7718ce2 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs @@ -1,8 +1,11 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using NUnit.Framework; using StackInjector.Attributes; +using StackInjector.Core; +using StackInjector.Settings; using CTkn = System.Threading.CancellationToken; @@ -75,8 +78,8 @@ public async Task SubmitAndCatchAsyncEnumerable () { var wrapper = Injector.AsyncFrom( (b,i,t) => b.ReturnArg(i,t) ); object - obj1 = new object(), - obj2 = new object(); + obj1 = new(), + obj2 = new(); wrapper.Submit(obj1); wrapper.Submit(obj2); @@ -144,20 +147,41 @@ public void ThrowsInvalidOnMultipleElaboration () } - [Test] + [Test][Timeout(1000)] public void SubmitWithEvent () { - using var wrapper = Injector.AsyncFrom( (b,i,t) => b.ReturnArg(i,t) ); - - var called = false; - wrapper.OnElaborated += ( obj ) => called = true; + 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(); + }; - var task = wrapper.SubmitAndGet(new object()); wrapper.Elaborate(); - task.Wait(); - - Assert.IsTrue(called); + 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/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs index 04958e4..8554896 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs @@ -70,20 +70,6 @@ public void ExternalAssemblyReference () } - [Test] - [Ignore("feature disabled.")] - public void ExternalAllAssemblyReference () - { - //var settings = SWS.With(); - //settings.MaskOptions.RegisterDomain(); - - - //var externalClass = Injector.From(settings).Entry.externalClass; - - //Assert.That(externalClass, Is.TypeOf()); - } - - // ---------- private interface INoImplementationThrower { void SomeMethod (); } diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs index 4966e39..b109ba5 100644 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs @@ -53,18 +53,22 @@ public void ServeStrict () } - [Test][Ignore("feature has to be reviewd")] + [Test]//[Ignore("feature has to be reviewd")] public void RemoveUnusedTypes () { var settings = StackWrapperSettings.Default; settings.Injection .RemoveUnusedTypesAfterInjection(); - var wrap1 = Injector.From( settings ); - var clone1 = wrap1.CloneCore(); + Assert.Multiple(() => + { + var wrap1 = Injector.From( ); + Assert.AreEqual(4, wrap1.CountServices()); - // base is removed after injecting from a class that doesn't need it - Assert.Throws(() => clone1.ToWrapper()); + // base is removed after injecting from a class that doesn't need it + var clone1 = wrap1.DeepCloneCore( settings ).ToWrapper( ); + Assert.AreEqual(2, clone1.CountServices()); + }); } @@ -76,6 +80,7 @@ public void AccessWrapper () Assert.AreSame(wrapper, wrapper.Entry.wrapper); } + [Test] public void ServeEnum () { @@ -116,27 +121,16 @@ public void AlwaysCreate () internal class Cloning { - - [Test][Ignore("feature removed. Review this later")] - public void RegisterAfterCloning () + [Test] + public void ExternalAfterCloning () { - ////// empty class - ////var wrapper1 = Injector.From(); - - ////Assert.Multiple(() => - ////{ - //// // BaseServiceNotFoundThrower uses a class in an external assembly - //// Assert.Throws(() => wrapper1.CloneCore().ToWrapper()); - - //// var settings = StackWrapperSettings.Default; - //// settings.MaskOptions - //// .RegisterAssemblyOf() - //// .RegisterAfterCloning(); - - //// Assert.DoesNotThrow(() => wrapper1.CloneCore(settings).ToWrapper()); - - //}); - + Assert.DoesNotThrow(() => + { + Injector + .From() // service with no dependency + .CloneCore() + .ToWrapper(); + }); } [Test] From a47bc0d8edb591706480c5e00682a2d4f880cb1a Mon Sep 17 00:00:00 2001 From: JacopoWolf Date: Sat, 10 Apr 2021 19:46:52 +0200 Subject: [PATCH 20/26] Update dotnet_pullr.yml possibly resolved bug with windows builds failing --- .github/workflows/dotnet_pullr.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dotnet_pullr.yml b/.github/workflows/dotnet_pullr.yml index 11988ee..b700b19 100644 --- a/.github/workflows/dotnet_pullr.yml +++ b/.github/workflows/dotnet_pullr.yml @@ -32,6 +32,9 @@ jobs: with: dotnet-version: '5.0.x' + - name: Clean cache + run: dotnet clean --configuration Release && dotnet nuget locals all --clear + - name: Install dependencies run: dotnet restore @@ -39,5 +42,5 @@ jobs: run: dotnet build --no-restore --configuration Release - name: Test - run: dotnet test --no-restore --configuration Release --logger "console;verbosity=detailed" + run: dotnet test --no-restore --configuration Release --logger "console;verbosity=detailed" From 83e86137d7fc6330ef3a56077907d4ac452bad2f Mon Sep 17 00:00:00 2001 From: Jacopo Date: Wed, 14 Apr 2021 03:48:59 +0200 Subject: [PATCH 21/26] Refactored test project and tests --- StackInjector/Core/IStackWrapperCore.cs | 2 +- .../InjectionCore.instantiation.cs | 2 +- StackInjector/Settings/MaskOptions.cs | 2 - .../StackInjector.TEST.BlackBox/Behaviour.cs | 60 ++++++ tests/StackInjector.TEST.BlackBox/Cloning.cs | 70 +++++++ .../CommonTestingMethods.cs | 29 --- .../Features/Test.InstantiationDiff.cs | 127 ------------ .../Features/Test.Versioning.cs | 63 ------ .../GlobalSuppressions.cs | 9 + tests/StackInjector.TEST.BlackBox/Injector.cs | 108 ++++++++++ .../SampleClassStructures/Simple.cs | 88 ++++++++ .../SimpleStructure.cs | 133 ------------ .../UseCases/Async.cs | 189 ------------------ .../UseCases/Exceptions.cs | 181 ----------------- .../UseCases/Sync.cs | 162 --------------- .../settings/Serving.cs | 106 ++++++++++ .../settings/Settings.cs | 20 ++ 17 files changed, 463 insertions(+), 888 deletions(-) create mode 100644 tests/StackInjector.TEST.BlackBox/Behaviour.cs create mode 100644 tests/StackInjector.TEST.BlackBox/Cloning.cs delete mode 100644 tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs delete mode 100644 tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs delete mode 100644 tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs create mode 100644 tests/StackInjector.TEST.BlackBox/GlobalSuppressions.cs create mode 100644 tests/StackInjector.TEST.BlackBox/Injector.cs create mode 100644 tests/StackInjector.TEST.BlackBox/SampleClassStructures/Simple.cs delete mode 100644 tests/StackInjector.TEST.BlackBox/SimpleStructure.cs delete mode 100644 tests/StackInjector.TEST.BlackBox/UseCases/Async.cs delete mode 100644 tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs delete mode 100644 tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs create mode 100644 tests/StackInjector.TEST.BlackBox/settings/Serving.cs create mode 100644 tests/StackInjector.TEST.BlackBox/settings/Settings.cs diff --git a/StackInjector/Core/IStackWrapperCore.cs b/StackInjector/Core/IStackWrapperCore.cs index a099879..4eb9a3f 100644 --- a/StackInjector/Core/IStackWrapperCore.cs +++ b/StackInjector/Core/IStackWrapperCore.cs @@ -24,7 +24,7 @@ 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 diff --git a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs index 415b1d8..8d92e1e 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs @@ -46,7 +46,7 @@ private object InstantiateService ( Type type ) this.instances.AddType(type); //try add this.instances[type].AddLast(instance); - this.instances.total_count++; + this.instances.total_count++; //! wtf this should always return the number of instances // if true, track instantiated objects if ( this.settings.Injection._trackInstancesDiff ) diff --git a/StackInjector/Settings/MaskOptions.cs b/StackInjector/Settings/MaskOptions.cs index e55ea41..d13f9e5 100644 --- a/StackInjector/Settings/MaskOptions.cs +++ b/StackInjector/Settings/MaskOptions.cs @@ -5,8 +5,6 @@ namespace StackInjector.Settings { - - //todo seealso custom mask exception /// /// Used to filter Types from the injection proces. /// When trying to inject masked Types an injection will be thrown.
diff --git a/tests/StackInjector.TEST.BlackBox/Behaviour.cs b/tests/StackInjector.TEST.BlackBox/Behaviour.cs new file mode 100644 index 0000000..2ac5343 --- /dev/null +++ b/tests/StackInjector.TEST.BlackBox/Behaviour.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using StackInjector.Attributes; +using StackInjector.Settings; + +namespace StackInjector.TEST.BlackBox +{ + [TestFixture] + public class Behaviour + { +#pragma warning disable 0649 + + [Service] private class _ReferenceLoopA {[Served] public _ReferenceLoopB loopB; } + + [Service] private class _ReferenceLoopB {[Served] public _ReferenceLoopA loopA; } + + + [Timeout(1000)] + [Test(Description = "verifies that A<->B does not throw an error when using Singleton references.")] + public void Avoid_CircularReference () + { + var wrapper = Injector.From<_ReferenceLoopA>(); + + Assert.Multiple(() => { + Assert.AreSame(wrapper.Entry, wrapper.Entry.loopB.loopA); + Assert.AreEqual(2, wrapper.CountServices()); + }); + } + + + //? should this maybe go to Inejctor + [Service] + private class _AlwaysCreateBase + { + [Served] public _AlwaysCreateInstance instance1; + [Served] public _AlwaysCreateInstance instance2; + } + + [Service(Pattern = InstantiationPattern.AlwaysCreate)] + private class _AlwaysCreateInstance { } + + [Test] + public void AlwaysCreate () + { + var wrapper = Injector.From<_AlwaysCreateBase>(); + + Assert.Multiple(() => + { + Assert.AreEqual(2, wrapper.GetServices<_AlwaysCreateInstance>().Count()); + CollectionAssert.AllItemsAreUnique(wrapper.GetServices<_AlwaysCreateInstance>()); + }); + + } + + } +} diff --git a/tests/StackInjector.TEST.BlackBox/Cloning.cs b/tests/StackInjector.TEST.BlackBox/Cloning.cs new file mode 100644 index 0000000..05a1e39 --- /dev/null +++ b/tests/StackInjector.TEST.BlackBox/Cloning.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using StackInjector.Core; +using StackInjector.Settings; +using StackInjector.TEST.Structures.Simple; + +namespace StackInjector.TEST.BlackBox +{ + [TestFixture] + public class Cloning + { + + [Test] + public void ExternalAfterCloning () + { + Assert.DoesNotThrow(() => + { + Injector + .From() // service with no dependency + .CloneCore() + .ToWrapper(); + }); + } + + [Test][Order(0)] + public void CloneSame () + { + var wrapper = Injector.From(); + + var cloneWrapper = wrapper.CloneCore().ToWrapper(); + + CollectionAssert.AreEquivalent(wrapper.GetServices(), cloneWrapper.GetServices()); + } + + [Test] + public void CloneNoRepetitionsSingleton () + { + var wrapper = Injector.From(); + + var clone = wrapper.CloneCore().ToWrapper(); + + Assert.AreSame(clone, clone.GetServices().Single()); + + } + + + [Test] + public void RemoveUnusedTypes () + { + var settings = StackWrapperSettings.Default; + settings.Injection + .RemoveUnusedTypesAfterInjection(); + + Assert.Multiple(() => + { + var wrap1 = Injector.From( ); + Assert.AreEqual(4, wrap1.CountServices()); + + // base is removed after injecting from a class that doesn't need it + var clone1 = wrap1.DeepCloneCore( settings ).ToWrapper( ); + Assert.AreEqual(2, clone1.CountServices()); + }); + } + + } +} diff --git a/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs b/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs deleted file mode 100644 index 46c2270..0000000 --- a/tests/StackInjector.TEST.BlackBox/CommonTestingMethods.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Threading.Tasks; -using NUnit.Framework; - -namespace StackInjector.TEST.BlackBox -{ - /// - /// common methods for every test class to inherith from. - /// - class CommonTestingMethods - { - // this is done because apaprently [Timeout] and [Retry] together just don't work - protected static void ExecuteTest ( int timeout, Action test ) - { - try - { - var task = Task.Run(test); - if ( !task.Wait(timeout)) - throw new TimeoutException("Timed out"); - } - catch ( Exception ex ) - { - //If the caught exception is not an assert exception but an unhandled exception. - if ( !(ex is AssertionException) ) - Assert.Fail(ex.Message); - } - } - } -} diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs deleted file mode 100644 index fdbe761..0000000 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.InstantiationDiff.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System.Linq; -using NUnit.Framework; -using StackInjector.Attributes; -using StackInjector.Exceptions; -using StackInjector.Settings; -using StackInjector.Wrappers; - -namespace StackInjector.TEST.BlackBox.Features -{ -#pragma warning disable CS0649 - - internal class InstantiationDiff : CommonTestingMethods - { - [Service] - private class WrapperBase - { - [Served] - public readonly ServiceA serviceA; - - public void Work () => this.serviceA.sharedCondition = true; - - } - - [Service] - private class ServiceA - { - public bool sharedCondition; - } - - - [Test] - public void SimpleClone () - { - var settings = StackWrapperSettings.Default; - settings.Injection - .TrackInstantiationDiff(); - - IStackWrapper wrapperA, wrapperB; - - wrapperA = Injector.From(settings); - wrapperB = wrapperA.CloneCore().ToWrapper(); - - - Assert.Multiple(() => - { - Assert.DoesNotThrow(() => wrapperB.Entry.Work()); - Assert.AreSame( - wrapperA.GetServices().First(), - wrapperB.GetServices().First() - ); - Assert.AreSame( - wrapperA.Settings, - wrapperB.Settings - ); - }); - } - - [Test] - public void SimpleCloneWithDispose () - { - var settings = StackWrapperSettings.Default; - settings.Injection - .TrackInstantiationDiff(); - - IStackWrapper wrapperB; - - using( var wrapperA = Injector.From(settings) ) - { - wrapperA.Start(e => e.Work()); - wrapperB = wrapperA.CloneCore().ToWrapper(); - } - - // after a deep clone there are no instances in wrapperB - Assert.Throws(() => wrapperB.Entry.Work()); - - } - - - [Test] - public void DeepClone () - { - var settings = StackWrapperSettings.Default; - settings.Injection - .TrackInstantiationDiff(); - - IStackWrapper wrapperB; - - var wrapperA = Injector.From(settings); - - wrapperA.Start(e => e.Work()); - wrapperB = wrapperA.DeepCloneCore().ToWrapper(); - - Assert.Multiple(() => - { - Assert.DoesNotThrow(() => wrapperB.Entry.Work()); - Assert.AreNotSame( - wrapperA.GetServices().First(), - wrapperB.GetServices().First() - ); - Assert.AreNotSame( - wrapperA.Settings, - wrapperB.Settings - ); - }); - } - - [Test] - public void DeepCloneWithDispose () - { - var settings = StackWrapperSettings.Default; - settings.Injection - .TrackInstantiationDiff(); - - IStackWrapper wrapperB; - - using( var wrapperA = Injector.From(settings) ) - { - wrapperA.Start(e => e.Work()); - wrapperB = wrapperA.DeepCloneCore().ToWrapper(); - } - - // wrapper B is a deep clone. Being different objects, disposing one won't interact with the other - Assert.DoesNotThrow(() => wrapperB.Entry.Work()); - - } - } -} \ No newline at end of file diff --git a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs b/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs deleted file mode 100644 index 8fafaa0..0000000 --- a/tests/StackInjector.TEST.BlackBox/Features/Test.Versioning.cs +++ /dev/null @@ -1,63 +0,0 @@ -using NUnit.Framework; -using StackInjector.Attributes; -using StackInjector.Settings; - -namespace StackInjector.TEST.BlackBox.Features -{ - internal class Versioning : CommonTestingMethods - { -#pragma warning disable CS0649 - - [Service] private class VersionClass {[Served] internal Level1A Level1_2; } - - [Test] - public void ServedVersioningClass () - { - var settings = StackWrapperSettings.Default; - settings.Injection - .VersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); - - var versionedService = Injector.From(settings).Entry.Level1_2; - - /* CLASSES ARE NOT VERSIONED, ONLY INTERFACES - * this is why this tests checks if the field is not of Level1_2 - */ - Assert.That(versionedService, Is.Not.InstanceOf()); - - } - - [Test] - public void ServedVersioningInterface () - { - var versionedService = Injector.From().Entry.level1; - - Assert.That(versionedService, Is.TypeOf()); - } - - - [Test] - public void SettingVersioningLatestMaj () - { - var settings = StackWrapperSettings.Default; - settings.Injection - .VersioningMethod(ServedVersionTargetingMethod.LatestMajor,true); - - var versionedService = Injector.From( settings ).Entry.level1; - - Assert.That(versionedService, Is.TypeOf()); - } - - - [Test] - public void SettingVersioningLatestMin () - { - var settings = StackWrapperSettings.Default; - settings.Injection - .VersioningMethod(ServedVersionTargetingMethod.LatestMinor,true); - - var versionedService = Injector.From( settings ).Entry.level1; - - Assert.That(versionedService, Is.TypeOf()); - } - } -} diff --git a/tests/StackInjector.TEST.BlackBox/GlobalSuppressions.cs b/tests/StackInjector.TEST.BlackBox/GlobalSuppressions.cs new file mode 100644 index 0000000..b72e7dc --- /dev/null +++ b/tests/StackInjector.TEST.BlackBox/GlobalSuppressions.cs @@ -0,0 +1,9 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +//NOTE: #pragma warning disable 0649 is used because it is a compile time warning. +[assembly: SuppressMessage("Style", "IDE1006", Justification = "for a design choise, private classes")] \ No newline at end of file diff --git a/tests/StackInjector.TEST.BlackBox/Injector.cs b/tests/StackInjector.TEST.BlackBox/Injector.cs new file mode 100644 index 0000000..da77ace --- /dev/null +++ b/tests/StackInjector.TEST.BlackBox/Injector.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.IO.Pipes; +using System.Linq; +using NUnit; +using NUnit.Framework; +using StackInjector.Attributes; +using StackInjector.Core; +using StackInjector.Settings; +using StackInjector.TEST.Structures.Simple; + +namespace StackInjector.TEST.BlackBox +{ + /* + * all of those tests use the default class configuration + */ + + [TestFixture] + public class Injection + { + +#pragma warning disable 0649 + + [Test] + public void From_Class () + { + var wrapper = Injector.From(); + var entry = wrapper.Entry; + + Assert.Multiple(() => { + + Assert.That(entry, Is.InstanceOf()); + 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()); + + }); + } + + [Test] + public void From_Interface () + { + var wrapper = Injector.From(); + var entry = wrapper.Entry; + + Assert.Multiple(() => { + + Assert.That(entry, Is.InstanceOf()); + var _entry = (Base)entry; + 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()); + + }); + } + + + + [Service] private class _AccessWrapper {[Served] public IStackWrapperCore wrapper; } + + [Test] + public void IsInjected_Wrapper () + { + var wrapper = Injector.From<_AccessWrapper>(); + + Assert.AreSame(wrapper, wrapper.Entry.wrapper); + } + + + + [Service] private class _AllSimpleLevel1s {[Served] public IEnumerable level1s; } + + [Test(Description = "the ienumerable should be a list of every class implementing ILevel1")] + public void ServeEnum_Interface () + { + var wrapper = Injector.From<_AllSimpleLevel1s>(); + + var level1s = wrapper.Entry.level1s; + + CollectionAssert.AreEquivalent( + expected: new[] { typeof(Level1_11), typeof(Level1_12), typeof(Level1_50), typeof(Level1b_20) }, + actual: level1s.Select(i => i.GetType()) + ); + } + + + [Service] private class _AllSimpleLevel1s_class {[Served] public IEnumerable level1s; } + + [Test(Description = "the ienumerable should be a list of every class inherithing from Level1_12")] + public void ServeEnum_Class () + { + var wrapper = Injector.From<_AllSimpleLevel1s_class>(); + + var level1s = wrapper.Entry.level1s; + + CollectionAssert.AreEquivalent( + expected: new Type[] { typeof(Level1_11), typeof(Level1b_20) }, + actual: level1s.Select(i => i.GetType()) + ); + } + + + + + } +} \ No newline at end of file diff --git a/tests/StackInjector.TEST.BlackBox/SampleClassStructures/Simple.cs b/tests/StackInjector.TEST.BlackBox/SampleClassStructures/Simple.cs new file mode 100644 index 0000000..e356660 --- /dev/null +++ b/tests/StackInjector.TEST.BlackBox/SampleClassStructures/Simple.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using StackInjector.Attributes; +using StackInjector.Core; +using StackInjector.Core.Cloning; +using StackInjector.Settings; + +namespace StackInjector.TEST.Structures.Simple +{ + + // remove unnecessary warning + // field is unused + // cannot assign a value different from null + +#pragma warning disable CS0649 + + #region base + + internal interface IBase { object Logic ( object input ); } + + [Service(Version = 1.0)] + internal class Base : IBase + { + [Served] + public Level1_11 level1A; + + [Served] + public Level1_12 level1B; + + public object Logic ( object input ) => input; + } + + #endregion + + #region level 1 + + internal interface ILevel1 { int Logic { get; } } + + [Service(Version = 1.1)] + internal class Level1_11 : ILevel1 + { + [Served] + public readonly Level2 level2; + + [Ignored] + public int Logic => 42; + } + + [Service(Version = 1.2)] + internal class Level1_12 : ILevel1 + { + [Served] + public readonly Level2 level2; + + [Ignored] + public int Logic => 40 + 2; + } + + [Service(Version = 5.0)] + internal class Level1_50 : ILevel1 + { + [Ignored] + public int Logic => 123; + } + + [Service(Version = 2.0)] + internal class Level1b_20 : Level1_11 + { + + } + + #endregion + + #region level 2 + + internal interface ILevel2 { int Logic2 { get; } } + + [Service(Version = 1.0)] + internal class Level2 : ILevel2 + { + [Ignored] + public int Logic2 => 1; + } + + #endregion + +#pragma warning restore + +} diff --git a/tests/StackInjector.TEST.BlackBox/SimpleStructure.cs b/tests/StackInjector.TEST.BlackBox/SimpleStructure.cs deleted file mode 100644 index 1dcea14..0000000 --- a/tests/StackInjector.TEST.BlackBox/SimpleStructure.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System.Collections.Generic; -using StackInjector.Attributes; -using StackInjector.Core; -using StackInjector.Core.Cloning; -using StackInjector.Settings; - -namespace StackInjector.TEST.BlackBox -{ - - // set as readonly, unused field -#pragma warning disable CS0649, IDE0044, IDE0051 - - - /* class structure - * - * Base - * - * Level1A - - * Level1_2 - * - * Level1B - - * - Level 2 - */ - - - #region base - - internal interface IBase { int Logic (); } - - [Service(Version = 1.0)] - internal class Base : IBase - { - [Served] - private Level1A level1A; - - [Served] - private Level1B level1B; - - public int Logic () => this.level1A.Logic + 5 + this.level1B.Logic; - } - - - [Service(Version = 2.0)] - internal class InterfaceVersionedBase - { - [Served(TargetingMethod = ServedVersionTargetingMethod.Exact, TargetVersion = 1.2)] - public ILevel1 level1; - } - - [Service] - internal class ForgotTheServedAttributeBase - { - public Level1A level1A; - - public Level1B Level1B { get; set; } - - public int SomeMethod () => this.level1A.Logic + this.Level1B.Logic; - } - - [Service] - internal class AccessWrapperBase - { - [Served] - public IStackWrapperCore wrapper; - - public IStackWrapperCore Clone () - => - this.wrapper.CloneCore().ToWrapper(); - } - - [Service] - internal class AllLevel1Base - { - [Served] - public IEnumerable level1s; - } - - - #endregion - - #region level 1 - - internal interface ILevel1 { int Logic { get; } } - - [Service(Version = 1.1)] - internal class Level1A : ILevel1 - { - [Served] - private Level2 level2; - - [Ignored] - public int Logic => this.level2.Logic2 + 15; - } - - [Service(Version = 1.2)] - internal class Level1B : ILevel1 - { - [Served] - private Level2 level2; - - [Ignored] - public int Logic => this.level2.Logic2 + 20; - } - - [Service(Version = 5.0)] - internal class Level1LatestVersion : ILevel1 - { - [Ignored] - public int Logic => 123; - } - - #endregion - - #region level 2 - - internal interface ILevel2 { int Logic2 { get; } } - - [Service(Version = 1.0)] - internal class Level2 : ILevel2 - { - [Ignored] - public int Logic2 => 1; - } - - [Service(Version = 2.0)] - internal class Level1_2 : Level1A - { - - } - - #endregion - -} diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs deleted file mode 100644 index 7718ce2..0000000 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Async.cs +++ /dev/null @@ -1,189 +0,0 @@ -using System; -using System.Collections.Generic; -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.UseCases -{ - -#pragma warning disable IDE0060, IDE0051, IDE0044, CS0169, CS0649 - - internal class Async : CommonTestingMethods - { - /*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 ) - { - 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] - [Retry(3)] - //[Timeout(1000)] - public void TaskCancellation () - { - ExecuteTest(1000, () => - { - var wrapper = Injector.AsyncFrom( (b,i,t) => b.WaitForever(i,t) ); - var task = wrapper.SubmitAndGet(new object()); - - var elaborationTask = wrapper.Elaborate(); - - wrapper.Dispose(); - - Assert.Multiple(() => - { - 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); - }); - } - - - } -} \ No newline at end of file diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs deleted file mode 100644 index 8554896..0000000 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Exceptions.cs +++ /dev/null @@ -1,181 +0,0 @@ -using System; -using System.Collections.Generic; -using NUnit.Framework; -using NUnit.Framework.Internal; -using StackInjector.Attributes; -using StackInjector.Exceptions; -using StackInjector.Settings; -using StackInjector.TEST.ExternalAssembly; - -using SWS = StackInjector.Settings.StackWrapperSettings; - -namespace StackInjector.TEST.BlackBox.UseCases -{ - -#pragma warning disable IDE0051, IDE0044, CS0169, CS0649 - - internal class Exceptions : CommonTestingMethods - { - // ---------- - - [Service] - private class BaseNotAServiceThrower {[Served] private List integers; } - - [Test] - public void ThrowsNotAService () - => Assert.Throws(() => Injector.From()); - - // ---------- - - private class BaseNotAService { } - - [Test] - public void ThrowsBaseNotAService () - => Assert.Throws(() => Injector.From()); - - // ---------- - - [Service] - private abstract class AbstractThrower { } - - [Test] - public void ThrowsOnAbstractClass () - => Assert.Throws( () => Injector.From() ); - - // ---------- - - // references class in unregistred external assembly - [Service] - internal class ClassInExternalAssemblyBase {[Served] public Externalclass externalClass; } - - [Test] - public void ThrowsServiceNotFound () - { - var settings = SWS.With( - mask: MaskOptions.BlackList - .Register(typeof(Externalclass)) - ); - - //todo change to specific mask exception - Assert.Throws(() => Injector.From(settings)); - } - - - [Test] - public void ExternalAssemblyReference () - { - var externalClass = Injector.From().Entry.externalClass; - - Assert.That(externalClass, Is.TypeOf()); - } - - - // ---------- - - private interface INoImplementationThrower { void SomeMethod (); } - [Service] private class BaseNoImplementationThrower {[Served] private INoImplementationThrower no; } - - [Test] - public void ThrowsImplementationNotFound () - => Assert.Throws(() => Injector.From()); - - // ---------- - [Service(Pattern = InstantiationPattern.AlwaysCreate)] private class InvalidEntryTypeThrower { } - - [Test] - public void ThrowsInvalidEntryType () - => Assert.Throws(() => Injector.From()); - - // ---------- - - [Service] - private class BaseNoParameterlessConstructorThrower - { public int test; public BaseNoParameterlessConstructorThrower ( int test ) => this.test = test; } - - [Test] - public void ThrowsMissingParameterlessConstructor () - => Assert.Throws(() => Injector.From()); - - // ---------- - - [Service] - private class BaseNoSetterThrower {[Served] public Base Base { get; } } - - [Test] - public void ThrowsNoSetter () - => Assert.Throws(() => Injector.From()); - - // ---------- - - [Service(Pattern = InstantiationPattern.AlwaysCreate)] - private class AlwaysCreateLoopInjectionThrower {[Served] private readonly AlwaysCreateLoopInjectionThrower loop; } - - [Service] - private class InstantiationPatternBase {[Served] private readonly AlwaysCreateLoopInjectionThrower loop; } - - [Test] - [Timeout(200)] - public void ThrowsInstLimitReach_AlwaysCreate () - { - Assert.Throws(() => Injector.From()); - } - - - // ---------- - - - [Service] - private class SingletonLoopInjectionNotThrowerBase { [Served] readonly SingletonLoopInjectionNotThrower pippo; } - - [Service(Pattern = InstantiationPattern.Singleton)] - private class SingletonLoopInjectionNotThrower { [Served] readonly SingletonLoopInjectionNotThrower self; } - - - [Test][Retry(3)] - //[Timeout(200)] - public void NotThrowsInstLimitReach_Singleton_wBase () - { - ExecuteTest(100, () => - { - var settings = SWS.Default; - settings.Injection - .LimitInstancesCount(2); - Assert.DoesNotThrow(() => Injector.From(settings)); - }); - } - - - [Test][Retry(3)] - //[Timeout(200)] - public void NotThrowsInstLimitReach_Singleton () - { - ExecuteTest(100, () => - { - var settings = SWS.Default; - settings.Injection.LimitInstancesCount(2); - Assert.DoesNotThrow(() => Injector.From(settings)); - }); - } - - // ---------- - - [Test] - [Timeout(500)] - public void ThrowsInstLimitReach_Cloned () - { - var settings = SWS.Default; - settings.Injection - .LimitInstancesCount(1); - Assert.Throws( () => Injector.From().CloneCore(settings).ToWrapper() ); - } - - // ---------- - - - [Test] - public void ThrowsOnMaskDisabled () - => Assert.Throws( () => MaskOptions.Disabled.Register() ); - - - } -} diff --git a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs b/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs deleted file mode 100644 index b109ba5..0000000 --- a/tests/StackInjector.TEST.BlackBox/UseCases/Sync.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Linq; -using NUnit.Framework; -using StackInjector.Attributes; -using StackInjector.Core; -using StackInjector.Exceptions; -using StackInjector.Settings; - -#pragma warning disable CS0649 -namespace StackInjector.TEST.BlackBox.UseCases -{ - internal class Sync : CommonTestingMethods - { - - [Test] - public void FromClass () - { - var baseClass = Injector.From().Entry; - - // asserts the whole structure works and references are correct. - Assert.AreEqual(42, baseClass.Logic()); - } - - - [Test] - public void FromInterface () - { - var baseClass = Injector.From().Entry; - - // asserts the whole structure works and references are correct. - Assert.AreEqual(42, baseClass.Logic()); - } - - - [Service] private class ReferenceLoopA {[Served] public ReferenceLoopB loopB; } - - [Service] private class ReferenceLoopB {[Served] public ReferenceLoopA loopA; } - - [Test] - public void CircularReference () => Assert.That(() => Injector.From(), Throws.Nothing); - - - [Test] - public void ServeStrict () - { - var settings = StackWrapperSettings.Default; - settings.Injection - .ServingMethod( StackWrapperSettings.ServeAllStrict, true ); - - var entry = Injector.From(settings).Entry; - - Assert.That(new object[] { entry.level1A, entry.Level1B }, Is.All.Null); - } - - - [Test]//[Ignore("feature has to be reviewd")] - public void RemoveUnusedTypes () - { - var settings = StackWrapperSettings.Default; - settings.Injection - .RemoveUnusedTypesAfterInjection(); - - Assert.Multiple(() => - { - var wrap1 = Injector.From( ); - Assert.AreEqual(4, wrap1.CountServices()); - - // base is removed after injecting from a class that doesn't need it - var clone1 = wrap1.DeepCloneCore( settings ).ToWrapper( ); - Assert.AreEqual(2, clone1.CountServices()); - }); - - } - - [Test] - public void AccessWrapper () - { - var wrapper = Injector.From(); - - Assert.AreSame(wrapper, wrapper.Entry.wrapper); - } - - - [Test] - public void ServeEnum () - { - var injected = Injector.From().Entry.level1s; - - CollectionAssert.AreEquivalent - ( - new Type[] { typeof(Level1A), typeof(Level1B), typeof(Level1LatestVersion), typeof(Level1_2) }, - injected.Select(i => i.GetType()) - ); - } - - // ----------- - - [Service] - private class AlwaysCreateBase - { - [Served] public AlwaysCreateInstance instance1; - [Served] public AlwaysCreateInstance instance2; - } - - [Service(Pattern = InstantiationPattern.AlwaysCreate)] - private class AlwaysCreateInstance { } - - [Test] - public void AlwaysCreate () - { - var wrapper = Injector.From(); - - Assert.Multiple(() => - { - Assert.AreEqual(2, wrapper.GetServices().Count()); - CollectionAssert.AllItemsAreUnique(wrapper.GetServices()); - }); - - } - - - internal class Cloning - { - [Test] - public void ExternalAfterCloning () - { - Assert.DoesNotThrow(() => - { - Injector - .From() // service with no dependency - .CloneCore() - .ToWrapper(); - }); - } - - [Test] - public void CloneSame () - { - var wrapper = Injector.From(); - - var cloneWrapper = wrapper.Entry.Clone(); - - CollectionAssert.AreEquivalent(wrapper.GetServices(), cloneWrapper.GetServices()); - } - - [Test] - public void CloneNoRepetitionsSingleton () - { - var wrapper = Injector.From(); - - var clone = wrapper.CloneCore().ToWrapper(); - - Assert.AreSame(clone, clone.GetServices().Single()); - - } - - - } - - - } -} \ No newline at end of file diff --git a/tests/StackInjector.TEST.BlackBox/settings/Serving.cs b/tests/StackInjector.TEST.BlackBox/settings/Serving.cs new file mode 100644 index 0000000..63d9cfa --- /dev/null +++ b/tests/StackInjector.TEST.BlackBox/settings/Serving.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NuGet.Frameworks; +using NUnit.Framework; +using NUnit.Framework.Constraints; +using StackInjector.Attributes; +using StackInjector.Settings; +using StackInjector.TEST.Structures.Simple; + +namespace StackInjector.TEST.BlackBox +{ + [TestFixture] + public class Serving + { + +#pragma warning disable 0649 + + + [Service] + private class _NoServedAttribute + { + public IBase field; + + //? for some fucked up reason if written as `public IBase property {get; set;} is considered a field?!?!?` + public IBase property { get => this._base; set => this._base = value; } + [Ignored]private IBase _base; + } + + static IEnumerable NoAtt_ServingGenerator () + { + // prop, field, servingm + yield return new(Is.Null, Is.Null, StackWrapperSettings.ServeAllStrict); + yield return new(Is.Not.Null, Is.Not.Null, StackWrapperSettings.ServeAll); + yield return new(Is.Null, Is.Not.Null, ServingMethods.Fields); + yield return new(Is.Not.Null, Is.Null, ServingMethods.Properties); + yield return new(Is.Null, Is.Null, ServingMethods.None); + yield return new(Is.Null, Is.Null, ServingMethods.Strict); + yield break; + } + + [Test] + [TestCaseSource(nameof(NoAtt_ServingGenerator))] + public void NoAtt ( NullConstraint prop, NullConstraint field, ServingMethods serving ) + { + var settings = StackWrapperSettings.Default; + settings.Injection + .ServingMethod(methods: serving, @override: true); + + var entry = Injector.From<_NoServedAttribute>(settings).Entry; + + + Assert.Multiple(() => + { + Assert.That(entry.property, prop, message: "property"); + Assert.That(entry.field, field, message: "field"); + }); + } + + + [Service] private class _YesServedAttribute + { + [Served] + public IBase field; + + [Served] + public IBase property { get => this._base; set => this._base = value; } + + [Ignored] + private IBase _base; + } + + static IEnumerable Att_ServingGenerator () + { + // prop, field, servingm + yield return new(Is.Not.Null, Is.Not.Null, StackWrapperSettings.ServeAllStrict); + yield return new(Is.Not.Null, Is.Not.Null, StackWrapperSettings.ServeAll); + yield return new(Is.Null, Is.Not.Null, ServingMethods.Fields); + yield return new(Is.Not.Null, Is.Null, ServingMethods.Properties); + yield return new(Is.Null, Is.Null, ServingMethods.None); + yield return new(Is.Null, Is.Null, ServingMethods.Strict); + yield break; + } + + [Test] + [TestCaseSource(nameof(Att_ServingGenerator))] + public void WithAtt ( NullConstraint prop, NullConstraint field, ServingMethods serving ) + { + var settings = StackWrapperSettings.Default; + settings.Injection + .ServingMethod(methods: serving, @override: true); + + var entry = Injector.From<_YesServedAttribute>(settings).Entry; + + + Assert.Multiple(() => + { + Assert.That(entry.property, prop, message: "property"); + Assert.That(entry.field, field, message: "field"); + }); + } + + } +} diff --git a/tests/StackInjector.TEST.BlackBox/settings/Settings.cs b/tests/StackInjector.TEST.BlackBox/settings/Settings.cs new file mode 100644 index 0000000..cb175b6 --- /dev/null +++ b/tests/StackInjector.TEST.BlackBox/settings/Settings.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using StackInjector.Attributes; +using StackInjector.Settings; +using StackInjector.TEST.Structures.Simple; + +namespace StackInjector.TEST.BlackBox.settings +{ + [TestFixture] + public class Settings + { + + + + } +} From a77b77d93e07249f840c3530d3c78f8335c193bd Mon Sep 17 00:00:00 2001 From: Jacopo Date: Wed, 14 Apr 2021 04:04:32 +0200 Subject: [PATCH 22/26] Update Injector.cs documentation update --- StackInjector/Injector.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/StackInjector/Injector.cs b/StackInjector/Injector.cs index 3470d28..93e166d 100644 --- a/StackInjector/Injector.cs +++ b/StackInjector/Injector.cs @@ -9,7 +9,6 @@ namespace StackInjector { /// /// Static factory class exposing methods to create new StackWrappers. - /// Note that using any of the exposed methods will analyze the whole target assembly. /// If you want to clone an existing structure, see /// /// @@ -17,8 +16,8 @@ namespace StackInjector public static partial class Injector { /// - /// Create a new from the entry point. - /// If no setting are specified the default ones will be used. + /// Create a new from the entry point + /// If no settings are specified the default ones will be used. /// /// The type of the entry point /// settings for this StackWrapper @@ -52,15 +51,19 @@ public static IStackWrapper From ( StackWrapperSettings settings = null ) /// /// Create a new generic asyncronous StackWrapper from the - /// entry class with the specified delegate to apply to apply as digest. + /// entry class with the specified delegate to apply as digest. + /// If no settings are specified the default ones will be used. + /// examples: + /// Injector.AsyncFrom<MyClass>( (e,i,t) => e.Digest(i,t) ) + /// Injector.AsyncFrom( async (MyClass e, object parameter, CancellationToken token) => e.Digest(parameter, token) ) + /// tip: you can use tuples to pass multiple arguments if needed
///
/// class from which start injection /// type of elements in input /// type of elements in output /// delegate used to call the relative method to perform on submitted items /// the settings to use with this object. If null, use default. - /// The created wrapper - /// Injector.AsyncFrom<MyClass>( (e,i,t) => e.Digeset(i,t) ) + /// The created asyncronous wrapper /// /// /// From 64869ddf6042e5fc138d52bba57eccdf5d3e8f90 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Thu, 15 Apr 2021 04:09:36 +0200 Subject: [PATCH 23/26] Update Cloning tests --- .../InjectionCore.instantiation.cs | 2 +- .../Core/InjectionCore/InjectionCore.serve.cs | 1 - tests/StackInjector.TEST.BlackBox/Cloning.cs | 106 ++++++++++++++---- .../SampleClassStructures/Simple.cs | 4 +- 4 files changed, 87 insertions(+), 26 deletions(-) diff --git a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs index 8d92e1e..415b1d8 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.instantiation.cs @@ -46,7 +46,7 @@ private object InstantiateService ( Type type ) this.instances.AddType(type); //try add this.instances[type].AddLast(instance); - this.instances.total_count++; //! wtf this should always return the number of instances + this.instances.total_count++; // if true, track instantiated objects if ( this.settings.Injection._trackInstancesDiff ) diff --git a/StackInjector/Core/InjectionCore/InjectionCore.serve.cs b/StackInjector/Core/InjectionCore/InjectionCore.serve.cs index c77b678..15de466 100644 --- a/StackInjector/Core/InjectionCore/InjectionCore.serve.cs +++ b/StackInjector/Core/InjectionCore/InjectionCore.serve.cs @@ -6,7 +6,6 @@ namespace StackInjector.Core { internal partial class InjectionCore { - internal void Serve ( bool cloned = false ) { // those don't need to be inside the lock. diff --git a/tests/StackInjector.TEST.BlackBox/Cloning.cs b/tests/StackInjector.TEST.BlackBox/Cloning.cs index 05a1e39..6d55c4e 100644 --- a/tests/StackInjector.TEST.BlackBox/Cloning.cs +++ b/tests/StackInjector.TEST.BlackBox/Cloning.cs @@ -4,9 +4,12 @@ using System.Text; using System.Threading.Tasks; using NUnit.Framework; +using StackInjector.Attributes; using StackInjector.Core; +using StackInjector.Exceptions; using StackInjector.Settings; using StackInjector.TEST.Structures.Simple; +using StackInjector.Wrappers; namespace StackInjector.TEST.BlackBox { @@ -14,42 +17,77 @@ 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 + [Test] - public void ExternalAfterCloning () + public void Shallow_IsSameCore () { - Assert.DoesNotThrow(() => - { - Injector - .From() // service with no dependency - .CloneCore() - .ToWrapper(); + var wrapper = Injector.From(); + + var clone = wrapper.CloneCore().ToWrapper(); + + Assert.Multiple(() => { + // settings is a copy + Assert.AreSame(wrapper.Settings, clone.Settings); + // all instances are same + CollectionAssert.AreEquivalent( wrapper.GetServices(), clone.GetServices() ); }); } - [Test][Order(0)] - public void CloneSame () + + [Test] + public void Shallow_DisposeSourceBoth () { - var wrapper = Injector.From(); + var settings = StackWrapperSettings.Default; + settings.Injection + .TrackInstantiationDiff(); - var cloneWrapper = wrapper.CloneCore().ToWrapper(); + IStackWrapper wrapperA, wrapperB; - CollectionAssert.AreEquivalent(wrapper.GetServices(), cloneWrapper.GetServices()); + using ( wrapperA = Injector.From(settings) ) + { + wrapperB = wrapperA.CloneCore().ToWrapper(); + } + + // wrapper B is a shallow clone of A. Sharing the core, disposing of one disposes the other. + Assert.Multiple(() => { + CollectionAssert.IsEmpty(wrapperA.GetServices()); + CollectionAssert.IsEmpty(wrapperB.GetServices()); + }); } + #endregion + + #region Deep Cloning + [Test] - public void CloneNoRepetitionsSingleton () + public void Deep_IsDifferentCore () { var wrapper = Injector.From(); - var clone = wrapper.CloneCore().ToWrapper(); + var clone = wrapper.DeepCloneCore().ToWrapper(); - Assert.AreSame(clone, clone.GetServices().Single()); + var allsrvcs = wrapper.GetServices().Concat(clone.GetServices()); + Assert.Multiple(() => { + // settings is a copy + Assert.AreNotSame(wrapper.Settings, clone.Settings); + // no duplicate instance reference + Assert.AreEqual(allsrvcs.Count(), allsrvcs.Distinct().Count()); + // all types are duplicated + Assert.That(allsrvcs.GroupBy(i => i.GetType()).Select(g => g.Count()), Is.All.EqualTo(2)); + }); } - - [Test] - public void RemoveUnusedTypes () + [Test] //? perhaps move to Settings + public void Deep_RemoveUnused () { var settings = StackWrapperSettings.Default; settings.Injection @@ -57,14 +95,38 @@ public void RemoveUnusedTypes () Assert.Multiple(() => { - var wrap1 = Injector.From( ); - Assert.AreEqual(4, wrap1.CountServices()); + var wrap = Injector.From( ); + Assert.AreEqual(4, wrap.CountServices()); // base is removed after injecting from a class that doesn't need it - var clone1 = wrap1.DeepCloneCore( settings ).ToWrapper( ); - Assert.AreEqual(2, clone1.CountServices()); + var clone = wrap.DeepCloneCore( settings ).ToWrapper( ); + Assert.AreEqual(2, clone.CountServices()); }); } + + [Test] + public void Deep_DisposeSourceNotClone () + { + var settings = StackWrapperSettings.Default; + settings.Injection + .TrackInstantiationDiff(); + + IStackWrapper wrapperA, wrapperB; + + using ( wrapperA = Injector.From(settings) ) + { + wrapperB = wrapperA.DeepCloneCore().ToWrapper(); + } + + // wrapper B is a deep clone of A. Being different objects, disposing one won't interact with the other + Assert.Multiple(() => { + CollectionAssert.IsEmpty(wrapperA.GetServices()); + CollectionAssert.IsNotEmpty(wrapperB.GetServices()); + }); + } + + #endregion + } } diff --git a/tests/StackInjector.TEST.BlackBox/SampleClassStructures/Simple.cs b/tests/StackInjector.TEST.BlackBox/SampleClassStructures/Simple.cs index e356660..e037478 100644 --- a/tests/StackInjector.TEST.BlackBox/SampleClassStructures/Simple.cs +++ b/tests/StackInjector.TEST.BlackBox/SampleClassStructures/Simple.cs @@ -15,7 +15,7 @@ namespace StackInjector.TEST.Structures.Simple #region base - internal interface IBase { object Logic ( object input ); } + internal interface IBase { void Logic ( ); } [Service(Version = 1.0)] internal class Base : IBase @@ -26,7 +26,7 @@ internal class Base : IBase [Served] public Level1_12 level1B; - public object Logic ( object input ) => input; + public void Logic ( ) { } } #endregion From a70935149a346a33c14daf3a390d3206998412c6 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sun, 2 May 2021 20:11:51 +0200 Subject: [PATCH 24/26] more tests refactoring - added Exceptions.cs --- .../StackInjector.TEST.BlackBox/Behaviour.cs | 34 +++---- tests/StackInjector.TEST.BlackBox/Cloning.cs | 11 +++ .../StackInjector.TEST.BlackBox/Exceptions.cs | 88 +++++++++++++++++++ tests/StackInjector.TEST.BlackBox/Injector.cs | 44 ++++++++++ .../settings/Serving.cs | 6 +- .../settings/Settings.cs | 5 +- 6 files changed, 162 insertions(+), 26 deletions(-) create mode 100644 tests/StackInjector.TEST.BlackBox/Exceptions.cs diff --git a/tests/StackInjector.TEST.BlackBox/Behaviour.cs b/tests/StackInjector.TEST.BlackBox/Behaviour.cs index 2ac5343..070afab 100644 --- a/tests/StackInjector.TEST.BlackBox/Behaviour.cs +++ b/tests/StackInjector.TEST.BlackBox/Behaviour.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using NUnit.Framework; using StackInjector.Attributes; +using StackInjector.Exceptions; using StackInjector.Settings; namespace StackInjector.TEST.BlackBox @@ -15,10 +16,8 @@ public class Behaviour #pragma warning disable 0649 [Service] private class _ReferenceLoopA {[Served] public _ReferenceLoopB loopB; } - [Service] private class _ReferenceLoopB {[Served] public _ReferenceLoopA loopA; } - [Timeout(1000)] [Test(Description = "verifies that A<->B does not throw an error when using Singleton references.")] public void Avoid_CircularReference () @@ -31,30 +30,21 @@ public void Avoid_CircularReference () }); } + // the base class is necessary because an entry point cannot be of type alwayscreate + [Service] private class _ReferenceLoop_AC_base {[Served]public _ReferenceLoop_AC loopinit; } + [Service(Pattern = InstantiationPattern.AlwaysCreate)] private class _ReferenceLoop_AC {[Served] public _ReferenceLoop_AC loopB; } - //? should this maybe go to Inejctor - [Service] - private class _AlwaysCreateBase - { - [Served] public _AlwaysCreateInstance instance1; - [Served] public _AlwaysCreateInstance instance2; - } - - [Service(Pattern = InstantiationPattern.AlwaysCreate)] - private class _AlwaysCreateInstance { } - - [Test] - public void AlwaysCreate () + [Timeout(1000)] + [Test(Description = "verifies that A<->B throws an exception when using AlwaysCreate references.")] + public void Limit_CircularReference () { - var wrapper = Injector.From<_AlwaysCreateBase>(); - - Assert.Multiple(() => - { - Assert.AreEqual(2, wrapper.GetServices<_AlwaysCreateInstance>().Count()); - CollectionAssert.AllItemsAreUnique(wrapper.GetServices<_AlwaysCreateInstance>()); - }); + var settings = StackWrapperSettings.Default; + settings.Injection.LimitInstancesCount(2); + Assert.Throws( ()=> Injector.From<_ReferenceLoop_AC_base>( settings ) ); + } + } } diff --git a/tests/StackInjector.TEST.BlackBox/Cloning.cs b/tests/StackInjector.TEST.BlackBox/Cloning.cs index 6d55c4e..35c38bf 100644 --- a/tests/StackInjector.TEST.BlackBox/Cloning.cs +++ b/tests/StackInjector.TEST.BlackBox/Cloning.cs @@ -63,6 +63,17 @@ public void Shallow_DisposeSourceBoth () }); } + + [Test] + public void Shallow_ThrowsInstancesLimit () + { + var settings = StackWrapperSettings.Default; + settings.Injection.LimitInstancesCount(1); + + Assert.Throws(() => Injector.From().CloneCore(settings).ToWrapper()); + + } + #endregion #region Deep Cloning diff --git a/tests/StackInjector.TEST.BlackBox/Exceptions.cs b/tests/StackInjector.TEST.BlackBox/Exceptions.cs new file mode 100644 index 0000000..4e86e5c --- /dev/null +++ b/tests/StackInjector.TEST.BlackBox/Exceptions.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using StackInjector.Attributes; +using StackInjector.Exceptions; +using StackInjector.Settings; +using StackInjector.TEST.Structures.Simple; + +namespace StackInjector.TEST.BlackBox +{ + +#pragma warning disable 0649, 0169, IDE0051 + + [TestFixture] + class Exceptions + { + + [Service] + private class BaseNotAServiceThrower {[Served] public int Cutelittleint { get; set; } } + + [Test] + public void ThrowsNotAService_Property () + { + Assert.Throws(() => Injector.From()); + } + + + + private class BaseNotAService { } + + [Test] + public void ThrowsNotAService_Base () + { + Assert.Throws(() => Injector.From()); + } + + + + [Service] + private abstract class AbstractThrower { } + + [Test] + public void ThrowsOnAbstractClass () + { + Assert.Throws(() => Injector.From()); + } + + + + private interface INoImplementationThrower { void SomeMethod (); } + [Service] private class BaseNoImplementationThrower {[Served] private readonly INoImplementationThrower no; } + + [Test] + public void ThrowsImplementationNotFound () + => Assert.Throws(() => Injector.From()); + + // ---------- + [Service(Pattern = InstantiationPattern.AlwaysCreate)] private class InvalidEntryTypeThrower { } + + [Test] + public void ThrowsInvalidEntryType () + => Assert.Throws(() => Injector.From()); + + // ---------- + + [Service] + private class BaseNoParameterlessConstructorThrower + { public int test; public BaseNoParameterlessConstructorThrower ( int test ) => this.test = test; } + + [Test] + public void ThrowsMissingParameterlessConstructor () + => Assert.Throws(() => Injector.From()); + + // ---------- + + [Service] + private class BaseNoSetterThrower {[Served] public Base Base { get; } } + + [Test] + public void ThrowsNoSetter () + => Assert.Throws(() => Injector.From()); + + + } +} diff --git a/tests/StackInjector.TEST.BlackBox/Injector.cs b/tests/StackInjector.TEST.BlackBox/Injector.cs index da77ace..8794a50 100644 --- a/tests/StackInjector.TEST.BlackBox/Injector.cs +++ b/tests/StackInjector.TEST.BlackBox/Injector.cs @@ -102,7 +102,51 @@ public void ServeEnum_Class () } + [Service] + private class _AlwaysCreateBase + { + [Served] public _AlwaysCreateInstance instance1; + [Served] public _AlwaysCreateInstance instance2; + } + + [Service(Pattern = InstantiationPattern.AlwaysCreate)] + private class _AlwaysCreateInstance { } + + [Test] + public void AlwaysCreate () + { + var wrapper = Injector.From<_AlwaysCreateBase>(); + + Assert.Multiple(() => + { + Assert.AreEqual(2, wrapper.GetServices<_AlwaysCreateInstance>().Count()); + CollectionAssert.AllItemsAreUnique(wrapper.GetServices<_AlwaysCreateInstance>()); + }); + + } + + + [Service] + private class _ExternalAssemblyReference_Class {[Served] public readonly ExternalAssembly.Externalclass externalclass; } + + [Test] + public void ExternalAssembly_NoRegistration_FromClass () + { + Assert.DoesNotThrow(() => Injector.From<_ExternalAssemblyReference_Class>()); + } + + + [Service] + private class _ExternalAssemblyReference_Interface {[Served] public readonly ExternalAssembly.IExternalClass externalclass; } + + [Test] + public void ExternalAssembly_NoRegistration_FromInterface () + { + Assert.DoesNotThrow(() => Injector.From<_ExternalAssemblyReference_Interface>()); + } + + //todo asas } } \ No newline at end of file diff --git a/tests/StackInjector.TEST.BlackBox/settings/Serving.cs b/tests/StackInjector.TEST.BlackBox/settings/Serving.cs index 63d9cfa..3a59082 100644 --- a/tests/StackInjector.TEST.BlackBox/settings/Serving.cs +++ b/tests/StackInjector.TEST.BlackBox/settings/Serving.cs @@ -24,7 +24,7 @@ private class _NoServedAttribute { public IBase field; - //? for some fucked up reason if written as `public IBase property {get; set;} is considered a field?!?!?` + // for some fucked up reason if written as `public IBase property {get; set;}` is considered a field?!?!? public IBase property { get => this._base; set => this._base = value; } [Ignored]private IBase _base; } @@ -43,7 +43,7 @@ static IEnumerable NoAtt_ServingGenerator () [Test] [TestCaseSource(nameof(NoAtt_ServingGenerator))] - public void NoAtt ( NullConstraint prop, NullConstraint field, ServingMethods serving ) + public void NoAttributes ( NullConstraint prop, NullConstraint field, ServingMethods serving ) { var settings = StackWrapperSettings.Default; settings.Injection @@ -86,7 +86,7 @@ static IEnumerable Att_ServingGenerator () [Test] [TestCaseSource(nameof(Att_ServingGenerator))] - public void WithAtt ( NullConstraint prop, NullConstraint field, ServingMethods serving ) + public void WithAtttributes ( NullConstraint prop, NullConstraint field, ServingMethods serving ) { var settings = StackWrapperSettings.Default; settings.Injection diff --git a/tests/StackInjector.TEST.BlackBox/settings/Settings.cs b/tests/StackInjector.TEST.BlackBox/settings/Settings.cs index cb175b6..4be24e1 100644 --- a/tests/StackInjector.TEST.BlackBox/settings/Settings.cs +++ b/tests/StackInjector.TEST.BlackBox/settings/Settings.cs @@ -8,12 +8,15 @@ using StackInjector.Settings; using StackInjector.TEST.Structures.Simple; -namespace StackInjector.TEST.BlackBox.settings +namespace StackInjector.TEST.BlackBox { [TestFixture] public class Settings { + [Test] + public void ThrowsOnMaskDisabled () + => Assert.Throws(() => MaskOptions.Disabled.Register()); } From 9e1fe11306cebfc319494503ad7681adf99b6e8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 29 May 2021 05:02:08 +0000 Subject: [PATCH 25/26] Bump Microsoft.NET.Test.Sdk in /tests/StackInjector.TEST.BlackBox Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 16.9.4 to 16.10.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Commits](https://github.com/microsoft/vstest/compare/v16.9.4...v16.10.0) 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 ad043e8..2567816 100644 --- a/tests/StackInjector.TEST.BlackBox/StackInjector.TEST.BlackBox.csproj +++ b/tests/StackInjector.TEST.BlackBox/StackInjector.TEST.BlackBox.csproj @@ -24,7 +24,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + From dcfdc29375deeb8ca3d89ae38c388cbc691db7d0 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Sun, 30 May 2021 20:45:16 +0200 Subject: [PATCH 26/26] Update nuget.yml --- .github/workflows/nuget.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index cdab459..c3a8c3a 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -8,6 +8,7 @@ on: jobs: test: + runs-on: ${{ matrix.os }} env: DOTNET_NOLOGO: true @@ -24,6 +25,9 @@ jobs: with: dotnet-version: '5.0.x' + - name: Clean cache + run: dotnet clean --configuration Release && dotnet nuget locals all --clear + - name: Install dependencies run: dotnet restore @@ -31,11 +35,12 @@ jobs: run: dotnet build --no-restore --configuration Release - name: Test - run: dotnet test --no-restore --configuration Release --logger "console;verbosity=detailed" + run: dotnet test --no-restore --configuration Release --logger "console;verbosity=detailed" release: + needs: [test] runs-on: ubuntu-latest @@ -47,12 +52,15 @@ jobs: with: dotnet-version: '5.0.x' + - name: Install dependencies + run: dotnet restore StackInjector/StackInjector.csproj + #run: echo ::set-env name=RELEASE_VERSION::${GITHUB_REF:10} - name: Version run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - name: Pack - run: dotnet pack StackInjector --configuration Release -p:PackageVersion=$RELEASE_VERSION + run: dotnet pack StackInjector --no-restore --configuration Release -p:PackageVersion=$RELEASE_VERSION - name: Push run: dotnet nuget push "StackInjector/bin/Release/StackInjector.$RELEASE_VERSION.nupkg" -k ${{ secrets.NUGET_KEY }} -s https://api.nuget.org/v3/index.json