- more exceptions replaced by bool return

ImplementExpressionTrees
Simon G 3 years ago
parent 7d7f3f417c
commit 1645718502
  1. 12
      LightweightIocContainer.Validation/IocValidator.cs
  2. 81
      LightweightIocContainer/IocContainer.cs

@ -71,14 +71,12 @@ public class IocValidator
private void TryResolve(Type type, object?[]? arguments, List<Exception> validationExceptions, bool isFactoryResolve = false) private void TryResolve(Type type, object?[]? arguments, List<Exception> validationExceptions, bool isFactoryResolve = false)
{ {
try (bool success, object _, Exception? exception) = _iocContainer.TryResolveNonGeneric(type, arguments, null, isFactoryResolve);
{ if (success)
_iocContainer.TryResolveNonGeneric(type, arguments, null, isFactoryResolve); return;
}
catch (Exception exception) if (exception is not null)
{
validationExceptions.Add(exception); validationExceptions.Add(exception);
}
} }
private T GetMock<T>() where T : class => new Mock<T>().Object; private T GetMock<T>() where T : class => new Mock<T>().Object;

@ -129,7 +129,17 @@ public class IocContainer : IIocContainer, IIocResolver
/// <param name="resolveStack">The current resolve stack</param> /// <param name="resolveStack">The current resolve stack</param>
/// <param name="isFactoryResolve">True if resolve is called from factory, false (default) if not</param> /// <param name="isFactoryResolve">True if resolve is called from factory, false (default) if not</param>
/// <returns>An instance of the given registered <see cref="Type"/></returns> /// <returns>An instance of the given registered <see cref="Type"/></returns>
private T ResolveInternal<T>(object?[]? arguments, List<Type>? resolveStack = null, bool isFactoryResolve = false) => ResolveInstance<T>(TryResolve<T>(arguments, resolveStack, isFactoryResolve)); private T ResolveInternal<T>(object?[]? arguments, List<Type>? resolveStack = null, bool isFactoryResolve = false)
{
(bool success, object resolvedObject, Exception? exception) = TryResolve<T>(arguments, resolveStack, isFactoryResolve);
if (success)
return ResolveInstance<T>(resolvedObject);
if (exception is not null)
throw exception;
throw new Exception("Resolve Error");
}
/// <summary> /// <summary>
/// Tries to resolve the given <see cref="Type"/> with the given arguments /// Tries to resolve the given <see cref="Type"/> with the given arguments
@ -145,28 +155,36 @@ public class IocContainer : IIocContainer, IIocResolver
/// <exception cref="MultitonResolveException">Tried resolving a multiton without scope argument</exception> /// <exception cref="MultitonResolveException">Tried resolving a multiton without scope argument</exception>
/// <exception cref="NoMatchingConstructorFoundException">No matching constructor for the given <see cref="Type"/> found</exception> /// <exception cref="NoMatchingConstructorFoundException">No matching constructor for the given <see cref="Type"/> found</exception>
/// <exception cref="InternalResolveException">Getting resolve stack failed without exception</exception> /// <exception cref="InternalResolveException">Getting resolve stack failed without exception</exception>
private object TryResolve<T>(object?[]? arguments, List<Type>? resolveStack, bool isFactoryResolve = false) private (bool success, object resolvedObject, Exception? exception) TryResolve<T>(object?[]? arguments, List<Type>? resolveStack, bool isFactoryResolve = false)
{ {
IRegistration registration = FindRegistration<T>() ?? throw new TypeNotRegisteredException(typeof(T)); IRegistration? registration = FindRegistration<T>();
if (registration == null)
return (false, new object(), new TypeNotRegisteredException(typeof(T)));
List<Type> internalResolveStack = resolveStack == null ? new List<Type>() : new List<Type>(resolveStack); List<Type> internalResolveStack = resolveStack == null ? new List<Type>() : new List<Type>(resolveStack);
internalResolveStack = CheckForCircularDependencies<T>(internalResolveStack); (bool success, internalResolveStack, CircularDependencyException? circularDependencyException) = CheckForCircularDependencies<T>(internalResolveStack);
if (!success && circularDependencyException is not null)
return (false, new object(), circularDependencyException);
if (!success)
throw new Exception("Invalid return type!");
object? existingInstance = TryGetExistingInstance<T>(registration, arguments); object? existingInstance = TryGetExistingInstance<T>(registration, arguments);
if (existingInstance != null) if (existingInstance != null)
return existingInstance; return (true, existingInstance, null);
switch (registration) switch (registration)
{ {
case IWithFactoryInternal { Factory: { } } when !isFactoryResolve: case IWithFactoryInternal { Factory: not null } when !isFactoryResolve:
throw new DirectResolveWithRegisteredFactoryNotAllowed(typeof(T)); return (false, new object(), new DirectResolveWithRegisteredFactoryNotAllowed(typeof(T)));
case ISingleTypeRegistration<T> singleTypeRegistration when singleTypeRegistration.InterfaceType.IsInterface && singleTypeRegistration.FactoryMethod == null: case ISingleTypeRegistration<T> { InterfaceType.IsInterface: true, FactoryMethod: null } singleTypeRegistration:
throw new InvalidRegistrationException($"Can't register an interface without its implementation type or without a factory method (Type: {singleTypeRegistration.InterfaceType})."); return (false, new object(), new InvalidRegistrationException($"Can't register an interface without its implementation type or without a factory method (Type: {singleTypeRegistration.InterfaceType})."));
case ISingleTypeRegistration<T> { FactoryMethod: { } } singleTypeRegistration: case ISingleTypeRegistration<T> { FactoryMethod: not null } singleTypeRegistration:
return new InternalFactoryMethodPlaceholder<T>(singleTypeRegistration); return (true, new InternalFactoryMethodPlaceholder<T>(singleTypeRegistration), null);
} }
if (registration is IWithParametersInternal { Parameters: { } } registrationWithParameters) if (registration is IWithParametersInternal { Parameters: not null } registrationWithParameters)
arguments = UpdateArgumentsWithRegistrationParameters(registrationWithParameters, arguments); arguments = UpdateArgumentsWithRegistrationParameters(registrationWithParameters, arguments);
Type registeredType = GetType<T>(registration); Type registeredType = GetType<T>(registration);
@ -176,7 +194,7 @@ public class IocContainer : IIocContainer, IIocResolver
if (registration is IMultitonRegistration multitonRegistration) if (registration is IMultitonRegistration multitonRegistration)
{ {
if (arguments == null || !arguments.Any()) if (arguments == null || !arguments.Any())
throw new MultitonResolveException("Can not resolve multiton without arguments.", registration.InterfaceType); return (false, new object(), new MultitonResolveException("Can not resolve multiton without arguments.", registration.InterfaceType));
object multitonScopeArgument = TryGetMultitonScopeArgument(multitonRegistration, arguments); object multitonScopeArgument = TryGetMultitonScopeArgument(multitonRegistration, arguments);
@ -185,12 +203,12 @@ public class IocContainer : IIocContainer, IIocResolver
} }
if (result) if (result)
return new InternalToBeResolvedPlaceholder(registeredType, registration, parametersToResolve); return (true, new InternalToBeResolvedPlaceholder(registeredType, registration, parametersToResolve), null);
if (exception != null) if (exception != null)
throw exception; return (false, new object(), exception);
throw new InternalResolveException("Getting resolve stack failed without exception."); return (false, new object(), new InternalResolveException("Getting resolve stack failed without exception."));
} }
/// <summary> /// <summary>
@ -207,9 +225,15 @@ public class IocContainer : IIocContainer, IIocResolver
/// <exception cref="MultitonResolveException">Tried resolving a multiton without scope argument</exception> /// <exception cref="MultitonResolveException">Tried resolving a multiton without scope argument</exception>
/// <exception cref="NoMatchingConstructorFoundException">No matching constructor for the given <see cref="Type"/> found</exception> /// <exception cref="NoMatchingConstructorFoundException">No matching constructor for the given <see cref="Type"/> found</exception>
/// <exception cref="InternalResolveException">Getting resolve stack failed without exception</exception> /// <exception cref="InternalResolveException">Getting resolve stack failed without exception</exception>
internal object? TryResolveNonGeneric(Type type, object?[]? arguments, List<Type>? resolveStack, bool isFactoryResolve = false) => internal (bool success, object resolvedObject, Exception? exception) TryResolveNonGeneric(Type type, object?[]? arguments, List<Type>? resolveStack, bool isFactoryResolve = false)
GenericMethodCaller.CallPrivate(this, nameof(TryResolve), type, arguments, resolveStack, isFactoryResolve); {
object? resolvedValue = GenericMethodCaller.CallPrivate(this, nameof(TryResolve), type, arguments, resolveStack, isFactoryResolve);
if (resolvedValue is not ValueTuple<bool, object, Exception?> resolvedTuple)
throw new Exception("Invalid return value!");
return resolvedTuple;
}
/// <summary> /// <summary>
/// Recursively resolve a <see cref="Type"/> with the given parameters for an <see cref="InternalToBeResolvedPlaceholder"/> /// Recursively resolve a <see cref="Type"/> with the given parameters for an <see cref="InternalToBeResolvedPlaceholder"/>
/// </summary> /// </summary>
@ -513,14 +537,13 @@ public class IocContainer : IIocContainer, IIocResolver
if (fittingArgument is InternalResolvePlaceholder) if (fittingArgument is InternalResolvePlaceholder)
{ {
try (bool success, object? resolvedObject, Exception? exception) = TryResolveNonGeneric(parameter.ParameterType, null, resolveStack);
{ if (success)
fittingArgument = TryResolveNonGeneric(parameter.ParameterType, null, resolveStack); fittingArgument = resolvedObject;
} else if (!success && exception is not null)
catch (Exception exception)
{
exceptions.Add(new ConstructorNotMatchingException(constructor, exception)); exceptions.Add(new ConstructorNotMatchingException(constructor, exception));
} else
throw new Exception("Invalid return value!");
if (fittingArgument is InternalResolvePlaceholder && passedArguments != null) if (fittingArgument is InternalResolvePlaceholder && passedArguments != null)
{ {
@ -615,16 +638,16 @@ public class IocContainer : IIocContainer, IIocResolver
/// <typeparam name="T">The given <see cref="Type"/></typeparam> /// <typeparam name="T">The given <see cref="Type"/></typeparam>
/// <returns>The new resolve stack</returns> /// <returns>The new resolve stack</returns>
/// <exception cref="CircularDependencyException">A circular dependency was detected</exception> /// <exception cref="CircularDependencyException">A circular dependency was detected</exception>
private List<Type> CheckForCircularDependencies<T>(List<Type>? resolveStack) private (bool success, List<Type> resolveStack, CircularDependencyException? exception) CheckForCircularDependencies<T>(List<Type>? resolveStack)
{ {
if (resolveStack == null) //first resolve call if (resolveStack == null) //first resolve call
resolveStack = new List<Type> {typeof(T)}; //create new stack and add the currently resolving type to the stack resolveStack = new List<Type> {typeof(T)}; //create new stack and add the currently resolving type to the stack
else if (resolveStack.Contains(typeof(T))) else if (resolveStack.Contains(typeof(T)))
throw new CircularDependencyException(typeof(T), resolveStack); //currently resolving type is still resolving -> circular dependency return (false, new List<Type>(), new CircularDependencyException(typeof(T), resolveStack)); //currently resolving type is still resolving -> circular dependency
else //not the first resolve call in chain but no circular dependencies for now else //not the first resolve call in chain but no circular dependencies for now
resolveStack.Add(typeof(T)); //add currently resolving type to the stack resolveStack.Add(typeof(T)); //add currently resolving type to the stack
return resolveStack; return (true, resolveStack, null);
} }
/// <summary> /// <summary>

Loading…
Cancel
Save