private bool CanConstruct(
            ConstructorInfo ctor,
            DependencyContainerResolveOptions options)
        {
            foreach (var parameter in ctor.GetParameters())
            {
                if (string.IsNullOrEmpty(parameter.Name))
                {
                    return(false);
                }

                var isParameterOverload = options.ConstructorParameters.ContainsKey(parameter.Name);

                if (parameter.ParameterType.IsPrimitive && !isParameterOverload)
                {
                    return(false);
                }

                if (!isParameterOverload &&
                    !CanResolve(new DependencyContainer.TypeRegistration(parameter.ParameterType), options.Clone()))
                {
                    return(false);
                }
            }

            return(true);
        }
Example #2
0
 public override object GetObject(
     Type requestedType,
     DependencyContainer container,
     DependencyContainerResolveOptions options)
 {
     return(_instance);
 }
Example #3
0
        /// <summary>
        /// Attempts to resolve all public property dependencies on the given object using the given resolve options.
        /// </summary>
        /// <param name="input">Object to "build up".</param>
        /// <param name="resolveOptions">Resolve options to use.</param>
        public void BuildUp(object input, DependencyContainerResolveOptions resolveOptions = null)
        {
            if (resolveOptions == null)
            {
                resolveOptions = DependencyContainerResolveOptions.Default;
            }

            var properties = input.GetType()
                             .GetProperties()
                             .Where(property => property.GetCacheGetMethod() != null && property.GetCacheSetMethod() != null &&
                                    !property.PropertyType.IsValueType);

            foreach (var property in properties.Where(property => property.GetValue(input, null) == null))
            {
                try
                {
                    property.SetValue(
                        input,
                        RegisteredTypes.ResolveInternal(new TypeRegistration(property.PropertyType), resolveOptions),
                        null);
                }
                catch (DependencyContainerResolutionException)
                {
                    // Catch any resolution errors and ignore them
                }
            }
        }
Example #4
0
 /// <summary>
 /// Attempts to predict whether a given named type can be resolved with the supplied constructor parameters options.
 ///
 /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists).
 /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail.
 ///
 /// Note: Resolution may still fail if user defined factory registrations fail to construct objects when called.
 /// </summary>
 /// <typeparam name="TResolveType">Type to resolve.</typeparam>
 /// <param name="name">Name of registration.</param>
 /// <param name="options">Resolution options.</param>
 /// <returns>Bool indicating whether the type can be resolved.</returns>
 public bool CanResolve <TResolveType>(
     string name = null,
     DependencyContainerResolveOptions options = null)
     where TResolveType : class
 {
     return(CanResolve(typeof(TResolveType), name, options));
 }
        internal object ConstructType(
            Type implementationType,
            ConstructorInfo constructor,
            DependencyContainerResolveOptions options = null)
        {
            var typeToConstruct = implementationType;

            if (constructor == null)
            {
                // Try and get the best constructor that we can construct
                // if we can't construct any then get the constructor
                // with the least number of parameters so we can throw a meaningful
                // resolve exception
                constructor = GetBestConstructor(typeToConstruct, options) ??
                              GetTypeConstructors(typeToConstruct).LastOrDefault();
            }

            if (constructor == null)
            {
                throw new DependencyContainerResolutionException(typeToConstruct);
            }

            var ctorParams = constructor.GetParameters();
            var args       = new object[ctorParams.Length];

            for (var parameterIndex = 0; parameterIndex < ctorParams.Length; parameterIndex++)
            {
                var currentParam = ctorParams[parameterIndex];

                try
                {
                    args[parameterIndex] = options?.ConstructorParameters.GetValueOrDefault(currentParam.Name, ResolveInternal(new DependencyContainer.TypeRegistration(currentParam.ParameterType), options.Clone()));
                }
                catch (DependencyContainerResolutionException ex)
                {
                    // If a constructor parameter can't be resolved
                    // it will throw, so wrap it and throw that this can't
                    // be resolved.
                    throw new DependencyContainerResolutionException(typeToConstruct, ex);
                }
                catch (Exception ex)
                {
                    throw new DependencyContainerResolutionException(typeToConstruct, ex);
                }
            }

            try
            {
                return(CreateObjectConstructionDelegateWithCache(constructor).Invoke(args));
            }
            catch (Exception ex)
            {
                throw new DependencyContainerResolutionException(typeToConstruct, ex);
            }
        }
Example #6
0
 /// <summary>
 /// Attempts to resolve a type using the given options.
 /// </summary>
 /// <param name="resolveType">Type to resolve.</param>
 /// <param name="options">Resolution options.</param>
 /// <param name="resolvedType">Resolved type or default if resolve fails.</param>
 /// <returns><c>true</c> if resolved successfully, <c>false</c> otherwise.</returns>
 public bool TryResolve(Type resolveType, DependencyContainerResolveOptions options, out object?resolvedType)
 {
     try
     {
         resolvedType = Resolve(resolveType, options: options);
         return(true);
     }
     catch (DependencyContainerResolutionException)
     {
         resolvedType = null;
         return(false);
     }
 }
Example #7
0
        public override object GetObject(
            Type requestedType,
            DependencyContainer container,
            DependencyContainerResolveOptions options)
        {
            var instance = _instance.Target;

            if (instance == null)
            {
                throw new DependencyContainerWeakReferenceException(_registerType);
            }

            return(instance);
        }
Example #8
0
 public override object GetObject(
     Type requestedType,
     DependencyContainer container,
     DependencyContainerResolveOptions options)
 {
     try
     {
         return(_factory.Invoke(container, options.ConstructorParameters));
     }
     catch (Exception ex)
     {
         throw new DependencyContainerResolutionException(_registerType, ex);
     }
 }
Example #9
0
 public override object GetObject(
     Type requestedType,
     DependencyContainer container,
     DependencyContainerResolveOptions options)
 {
     try
     {
         return(container.RegisteredTypes.ConstructType(_registerImplementation, Constructor, options));
     }
     catch (DependencyContainerResolutionException ex)
     {
         throw new DependencyContainerResolutionException(_registerType, ex);
     }
 }
Example #10
0
 /// <summary>
 /// Attempts to resolve a type using the given options.
 /// </summary>
 /// <typeparam name="TResolveType">Type to resolve.</typeparam>
 /// <param name="options">Resolution options.</param>
 /// <param name="resolvedType">Resolved type or default if resolve fails.</param>
 /// <returns><c>true</c> if resolved successfully, <c>false</c> otherwise.</returns>
 public bool TryResolve <TResolveType>(DependencyContainerResolveOptions options, out TResolveType?resolvedType)
     where TResolveType : class
 {
     try
     {
         resolvedType = Resolve <TResolveType>(options: options);
         return(true);
     }
     catch (DependencyContainerResolutionException)
     {
         resolvedType = default;
         return(false);
     }
 }
Example #11
0
        public override object GetObject(
            Type requestedType,
            DependencyContainer container,
            DependencyContainerResolveOptions options)
        {
            if (!(_factory.Target is Func <DependencyContainer, Dictionary <string, object>, object> factory))
            {
                throw new DependencyContainerWeakReferenceException(_registerType);
            }

            try
            {
                return(factory.Invoke(container, options.ConstructorParameters));
            }
            catch (Exception ex)
            {
                throw new DependencyContainerResolutionException(_registerType, ex);
            }
        }
Example #12
0
        public override object GetObject(
            Type requestedType,
            DependencyContainer container,
            DependencyContainerResolveOptions options)
        {
            if (options.ConstructorParameters.Count != 0)
            {
                throw new ArgumentException("Cannot specify parameters for singleton types");
            }

            lock (_singletonLock)
            {
                if (_current == null)
                {
                    _current = container.RegisteredTypes.ConstructType(_registerImplementation, Constructor, options);
                }
            }

            return(_current);
        }
Example #13
0
 /// <summary>
 /// Attempts to predict whether a given type can be resolved with the supplied constructor parameters options.
 /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists).
 /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail.
 /// Note: Resolution may still fail if user defined factory registrations fail to construct objects when called.
 /// </summary>
 /// <param name="resolveType">Type to resolve.</param>
 /// <param name="name">The name.</param>
 /// <param name="options">Resolution options.</param>
 /// <returns>
 /// Bool indicating whether the type can be resolved.
 /// </returns>
 public bool CanResolve(
     Type resolveType,
     string name = null,
     DependencyContainerResolveOptions options = null) =>
 RegisteredTypes.CanResolve(new TypeRegistration(resolveType, name), options);
        internal object ResolveInternal(
            DependencyContainer.TypeRegistration registration,
            DependencyContainerResolveOptions options = null)
        {
            if (options == null)
            {
                options = DependencyContainerResolveOptions.Default;
            }

            // Attempt container resolution
            if (TryGetValue(registration, out var factory))
            {
                try
                {
                    return(factory.GetObject(registration.Type, _dependencyContainer, options));
                }
                catch (DependencyContainerResolutionException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    throw new DependencyContainerResolutionException(registration.Type, ex);
                }
            }

            // Attempt to get a factory from parent if we can
            var bubbledObjectFactory = GetParentObjectFactory(registration);

            if (bubbledObjectFactory != null)
            {
                try
                {
                    return(bubbledObjectFactory.GetObject(registration.Type, _dependencyContainer, options));
                }
                catch (DependencyContainerResolutionException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    throw new DependencyContainerResolutionException(registration.Type, ex);
                }
            }

            // Fail if requesting named resolution and settings set to fail if unresolved
            if (!string.IsNullOrEmpty(registration.Name) && options.NamedResolutionFailureAction ==
                DependencyContainerNamedResolutionFailureAction.Fail)
            {
                throw new DependencyContainerResolutionException(registration.Type);
            }

            // Attempted unnamed fallback container resolution if relevant and requested
            if (!string.IsNullOrEmpty(registration.Name) && options.NamedResolutionFailureAction ==
                DependencyContainerNamedResolutionFailureAction.AttemptUnnamedResolution)
            {
                if (TryGetValue(new DependencyContainer.TypeRegistration(registration.Type, string.Empty), out factory))
                {
                    try
                    {
                        return(factory.GetObject(registration.Type, _dependencyContainer, options));
                    }
                    catch (DependencyContainerResolutionException)
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        throw new DependencyContainerResolutionException(registration.Type, ex);
                    }
                }
            }

            // Attempt unregistered construction if possible and requested
            var isValid = (options.UnregisteredResolutionAction ==
                           DependencyContainerUnregisteredResolutionAction.AttemptResolve) ||
                          (registration.Type.IsGenericType && options.UnregisteredResolutionAction ==
                           DependencyContainerUnregisteredResolutionAction.GenericsOnly);

            return(isValid && !registration.Type.IsAbstract && !registration.Type.IsInterface
                ? ConstructType(registration.Type, null, options)
                : throw new DependencyContainerResolutionException(registration.Type));
        }
 private ConstructorInfo GetBestConstructor(
     Type type,
     DependencyContainerResolveOptions options)
 => type.IsValueType ? null : GetTypeConstructors(type).FirstOrDefault(ctor => CanConstruct(ctor, options));
        internal bool CanResolve(
            DependencyContainer.TypeRegistration registration,
            DependencyContainerResolveOptions options = null)
        {
            if (options == null)
            {
                options = DependencyContainerResolveOptions.Default;
            }

            var checkType = registration.Type;
            var name      = registration.Name;

            if (TryGetValue(new DependencyContainer.TypeRegistration(checkType, name), out var factory))
            {
                if (factory.AssumeConstruction)
                {
                    return(true);
                }

                if (factory.Constructor == null)
                {
                    return(GetBestConstructor(factory.CreatesType, options) != null);
                }

                return(CanConstruct(factory.Constructor, options));
            }

            // Fail if requesting named resolution and settings set to fail if unresolved
            // Or bubble up if we have a parent
            if (!string.IsNullOrEmpty(name) && options.NamedResolutionFailureAction ==
                DependencyContainerNamedResolutionFailureAction.Fail)
            {
                return(_dependencyContainer.Parent?.RegisteredTypes.CanResolve(registration, options.Clone()) ?? false);
            }

            // Attempted unnamed fallback container resolution if relevant and requested
            if (!string.IsNullOrEmpty(name) && options.NamedResolutionFailureAction ==
                DependencyContainerNamedResolutionFailureAction.AttemptUnnamedResolution)
            {
                if (TryGetValue(new DependencyContainer.TypeRegistration(checkType), out factory))
                {
                    if (factory.AssumeConstruction)
                    {
                        return(true);
                    }

                    return(GetBestConstructor(factory.CreatesType, options) != null);
                }
            }

            // Check if type is an automatic lazy factory request or an IEnumerable<ResolveType>
            if (IsAutomaticLazyFactoryRequest(checkType) || registration.Type.IsIEnumerable())
            {
                return(true);
            }

            // Attempt unregistered construction if possible and requested
            // If we cant', bubble if we have a parent
            if ((options.UnregisteredResolutionAction ==
                 DependencyContainerUnregisteredResolutionAction.AttemptResolve) ||
                (checkType.IsGenericType && options.UnregisteredResolutionAction ==
                 DependencyContainerUnregisteredResolutionAction.GenericsOnly))
            {
                return((GetBestConstructor(checkType, options) != null) ||
                       (_dependencyContainer.Parent?.RegisteredTypes.CanResolve(registration, options.Clone()) ?? false));
            }

            // Bubble resolution up the container tree if we have a parent
            return(_dependencyContainer.Parent != null && _dependencyContainer.Parent.RegisteredTypes.CanResolve(registration, options.Clone()));
        }
Example #17
0
 /// <summary>
 /// Create the type.
 /// </summary>
 /// <param name="requestedType">Type user requested to be resolved.</param>
 /// <param name="container">Container that requested the creation.</param>
 /// <param name="options">The options.</param>
 /// <returns> Instance of type. </returns>
 public abstract object GetObject(
     Type requestedType,
     DependencyContainer container,
     DependencyContainerResolveOptions options);
Example #18
0
 /// <summary>
 /// Attempts to resolve a named type using specified options and the supplied constructor parameters.
 ///
 /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists).
 /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail.
 /// </summary>
 /// <param name="resolveType">Type to resolve.</param>
 /// <param name="name">Name of registration.</param>
 /// <param name="options">Resolution options.</param>
 /// <returns>Instance of type.</returns>
 /// <exception cref="DependencyContainerResolutionException">Unable to resolve the type.</exception>
 public object Resolve(
     Type resolveType,
     string name = null,
     DependencyContainerResolveOptions options = null)
 => RegisteredTypes.ResolveInternal(new TypeRegistration(resolveType, name), options ?? DependencyContainerResolveOptions.Default);