Skip to content
This repository was archived by the owner on Feb 14, 2022. It is now read-only.
Open

4.0.0 #183

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion StackInjector/Core/AsyncStackWrapperCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public CancellationToken PendingTasksCancellationToken


// register an event that in case the list is empty, release the empty event listener.
internal AsyncStackWrapperCore ( InjectionCore core, Type toRegister ) : base(core, toRegister)
internal AsyncStackWrapperCore ( InjectionCore core ) : base(core)
{
this.cancelPendingTasksSource.Token.Register(this.ReleaseListAwaiter);
}
Expand Down
63 changes: 18 additions & 45 deletions StackInjector/Core/AsyncStackWrapperCore.logic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using StackInjector.Settings;

namespace StackInjector.Core
{
Expand Down Expand Up @@ -40,7 +39,13 @@ public bool AnyTaskCompleted ()

public async IAsyncEnumerable<T> Elaborated ()
{
this.EnsureExclusiveExecution(true);
// begin elaboration
lock ( this._listAccessLock )
{
if ( this._exclusiveExecution )
throw new InvalidOperationException();
this._exclusiveExecution = true;
}

while ( !this.cancelPendingTasksSource.IsCancellationRequested )
{
Expand All @@ -62,8 +67,11 @@ public async IAsyncEnumerable<T> Elaborated ()
}
}

// no more elaborating
lock ( this._listAccessLock )
{
this._exclusiveExecution = false;
}

}

Expand All @@ -77,50 +85,15 @@ public async Task Elaborate ()
// true if outher loop is to break
private async Task<bool> OnNoTasksLeft ()
{
// to not repeat code
Task listAwaiter ()
{
return this._emptyListAwaiter.WaitAsync();
}

switch ( this.Settings.Runtime._asyncWaitingMethod )
{

case AsyncWaitingMethod.Exit:
default:

return true;


case AsyncWaitingMethod.Wait:

// wait for a signal of the list not being empty anymore
await listAwaiter().ConfigureAwait(true);
return false;
if ( this.Settings.Runtime._asyncWaitTime == 0 )
return true;


case AsyncWaitingMethod.Timeout:
var list = listAwaiter();
var timeout = Task.Delay( this.Settings.Runtime._asyncWaitTime );

// if the timeout elapses first, then stop waiting
return (await Task.WhenAny(list, timeout).ConfigureAwait(true)) == timeout;
}
}

private void EnsureExclusiveExecution ( bool set = false )
{
lock ( this._listAccessLock ) // reused lock
{
if ( this._exclusiveExecution )
throw new InvalidOperationException();

if ( set )
this._exclusiveExecution = set;
}
return !(await this._emptyListAwaiter.WaitAsync(
this.Settings.Runtime._asyncWaitTime,
this.PendingTasksCancellationToken
)
.ConfigureAwait(true));
}



}
}
}
3 changes: 1 addition & 2 deletions StackInjector/Core/IStackWrapperCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ public interface IStackWrapperCore : IDisposable, ICloneableCore
/// <typeparam name="T"></typeparam>
IEnumerable<T> GetServices<T> ();

//! description is wrong
/// <summary>
/// The current number of all tracked services.<br/>
/// Does also include the Wrapper, so if you want all the instances
/// Does also include the Wrapper, so if you want just the instances
/// <c>wrapper.CountServices()-1</c>
/// </summary>
int CountServices ();
Expand Down
16 changes: 8 additions & 8 deletions StackInjector/Core/InjectionCore/InjectionCore.injection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ private void InjectFields ( Type type, object instance, ref List<object> used, b
{
var fields =
type.GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance )
.Where( f => f.GetCustomAttribute<IgnoredAttribute>() is null );

if ( strict )
fields = fields.Where(field => field.GetCustomAttribute<ServedAttribute>() != null);
.Where( f =>
f.GetCustomAttribute<IgnoredAttribute>() is null
&& (!strict||f.GetCustomAttribute<ServedAttribute>() != null) //if not strict, skip this check
);

foreach ( var serviceField in fields )
{
Expand All @@ -78,10 +78,10 @@ private void InjectProperties ( Type type, object instance, ref List<object> use
{
var properties =
type.GetProperties( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance )
.Where( p => p.GetCustomAttribute<IgnoredAttribute>() is null );

if ( strict )
properties = properties.Where(property => property.GetCustomAttribute<ServedAttribute>() != null);
.Where( p =>
p.GetCustomAttribute<IgnoredAttribute>() is null
&& (!strict || p.GetCustomAttribute<ServedAttribute>() != null) //if not strict, skip this check
);

foreach ( var serviceProperty in properties )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ private object OfTypeOrInstantiate ( Type type )
if ( serviceAtt == null )
throw new NotAServiceException(type, $"Type {type.FullName} is not a [Service]");

////if( !this.instances.ContainsKey(type) )
//// throw new ServiceNotFoundException(type, $"The type {type.FullName} is not in a registred assembly!");


return serviceAtt.Pattern switch
{
Expand All @@ -40,7 +37,7 @@ private object InstantiateService ( Type type )

//todo add more constructor options
if ( type.GetConstructor(Array.Empty<Type>()) == null )
throw new MissingParameterlessConstructorException(type, $"Missing parameteless constructor for {type.FullName}");
throw new InvalidConstructorException(type, $"Missing parameteless constructor for {type.FullName}");

var instance = Activator.CreateInstance(type);

Expand Down
37 changes: 15 additions & 22 deletions StackInjector/Core/InjectionCore/InjectionCore.reflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,34 @@ private Type ClassOrVersionFromInterface ( Type type, ServedAttribute servedAttr
{
if ( type.IsInterface )
{
IEnumerable<Type> versions = this.instances.TypesAssignableFrom(type);
IEnumerable<Type> versions = this.Version(type, servedAttribute);

// is there already an implementation for the interface?
if ( versions.Any() )
{
return versions.First();
//todo check for multiple valid versions
var t = versions.First();
_MaskPass(t);
return t;
}

if ( servedAttribute is null )
throw new ImplementationNotFoundException(type, $"can't find [Service] for interface {type.Name}");
else
{
versions = this.Version(type, servedAttribute);
if ( versions.Any() )
{
var t = versions.First();
MaskPass(t);
return t;
}

if ( servedAttribute is null )
throw new ImplementationNotFoundException(type, $"can't find [Service] for interface {type.Name}");
else
throw new ImplementationNotFoundException(type, $"can't find [Service] for {type.Name} v{servedAttribute.TargetVersion}");
}
throw new ImplementationNotFoundException(type, $"can't find [Service] for {type.Name} v{servedAttribute.TargetVersion}");

}
else
{
MaskPass(type);
_MaskPass(type);
return type;
}


void MaskPass ( Type type )
// exception check and thrower
void _MaskPass ( Type type )
{
if ( this.settings.Mask.IsMasked(type) )
if ( this.settings.Mask.IsMasked(type) ) //todo create custom exception
throw new InvalidOperationException($"Type {type.Name} is { (this.settings.Mask._isWhiteList ? "not whitelisted" : "blacklisted")}");
//todo create custom exception

}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ internal T GetEntryPoint<T> ()
: throw new InvalidEntryTypeException
(
this.EntryType,
$"No instance found for entry type {this.EntryType.FullName}",
innerException: new ServiceNotFoundException(typeof(T), string.Empty)
$"No instance found for entry type {this.EntryType.FullName}"
);
}

Expand Down
34 changes: 26 additions & 8 deletions StackInjector/Core/InjectionCore/InjectionCore.versioning.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,40 @@ namespace StackInjector.Core
{
internal partial class InjectionCore
{
private static readonly Type _istackwrappercore = typeof(IStackWrapperCore);

// performs versioning on the specified type
private IEnumerable<Type> Version ( Type targetType, ServedAttribute servedAttribute )
{
if ( targetType.IsSubclassOf(_istackwrappercore) || targetType == _istackwrappercore )
return this.instances.TypesAssignableFrom(targetType);

if ( this.settings.Versioning._customBindings != null &&
this.settings.Versioning._customBindings.TryGetValue(targetType, out var t) )
{
return Enumerable.Repeat(t, 1);
}


var targetVersion = servedAttribute?.TargetVersion ?? 0.0;
var method =
(this.settings.Injection._overrideTargetingMethod || servedAttribute is null || !(servedAttribute._targetingDefined))
? this.settings.Injection._targetingMethod
(this.settings.Versioning._overrideTargetingMethod || servedAttribute is null || !(servedAttribute._targetingDefined))
? this.settings.Versioning._targetingMethod
: servedAttribute.TargetingMethod;


////var candidateTypes = this.instances.TypesAssignableFrom(targetType);
var candidateTypes = targetType
.Assembly
.GetTypes()
.Where( t => t.IsClass && !t.IsAbstract && targetType.IsAssignableFrom(t));
IEnumerable<TypeInfo> candidateTypes =
(this.settings.Versioning.AssemblyLookUpOrder.Any())
?
this.settings.Versioning
.AssemblyLookUpOrder
.SelectMany( a => a.DefinedTypes )
.Where( t => t.IsClass && !t.IsAbstract
&& targetType.IsAssignableFrom(t) && !this.settings.Mask.IsMasked(t) )
:
targetType
.Assembly
.DefinedTypes
.Where( t => t.IsClass && !t.IsAbstract && targetType.IsAssignableFrom(t) );


return method switch
Expand Down
3 changes: 2 additions & 1 deletion StackInjector/Core/InstancesHolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ internal bool AddType ( Type type )
return this.TryAdd(type, new LinkedList<object>());
}

internal void CountAllInstances ()
internal int CountAllInstances ()
{
this.total_count = 0;
foreach ( var pair in this )
this.total_count += pair.Value.Count;
return this.total_count;
}


Expand Down
20 changes: 11 additions & 9 deletions StackInjector/Core/StackWrapperCore.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using StackInjector.Core.Cloning;
using StackInjector.Settings;
Expand All @@ -18,15 +17,16 @@ public ref readonly StackWrapperSettings Settings
private protected readonly InjectionCore Core;


public StackWrapperCore ( InjectionCore core, Type toRegister )
public StackWrapperCore ( InjectionCore core )
{
this.Core = core;

// add this wrapper to possible instances
if ( !this.Core.instances.AddType(toRegister) )
this.Core.instances[toRegister].Clear();
this.Core.instances[toRegister].AddFirst(this);

var registerAs = this.GetType();
if ( !this.Core.instances.AddType(registerAs) )
this.Core.instances[registerAs].Clear();
this.Core.instances[registerAs].AddFirst(this);

}


Expand All @@ -38,8 +38,10 @@ public IEnumerable<T> GetServices<T> ()
.Select(o => (T)o);
}

public int CountServices () => this.Core.instances.total_count;

public int CountServices ()
{
return this.Core.instances.CountAllInstances();
}

public IClonedCore CloneCore ( StackWrapperSettings settings = null )
{
Expand Down
22 changes: 22 additions & 0 deletions StackInjector/Exceptions/InvalidConstructorException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;

namespace StackInjector.Exceptions
{
/// <summary>
/// Thrown when a class has no parameterless constructor to call.
/// </summary>
public sealed class InvalidConstructorException : StackInjectorException
{
internal InvalidConstructorException () { }

internal InvalidConstructorException ( Type type, string message ) : base(message)
{
this.SourceType = type;
}

internal InvalidConstructorException ( string message ) : base(message) { }

internal InvalidConstructorException ( string message, Exception innerException ) : base(message, innerException) { }

}
}

This file was deleted.

Loading