Ejemplo n.º 1
0
        /// <summary>
        /// Gets a Dictionary of errors and their corresponding types to help diagnose possible issues
        /// that resulted in the ContainerResolutionException.
        /// </summary>
        /// <returns>A <see cref="Dictionary{Type, Exception}"/> mapping types that encountered given exceptions in the resolution process.</returns>
        public ContainerResolutionErrorCollection GetErrors()
        {
            var errors = new ContainerResolutionErrorCollection();

            if (IsKnownIssue)
            {
                return(errors);
            }

            var implementingType = TryFindImplementingType();

            if (implementingType is null)
            {
                errors.Add(ServiceType, new ContainerResolutionException(ServiceType, MissingRegistration));
                return(errors);
            }
            else if (implementingType.IsAbstract)
            {
                errors.Add(ServiceType, new ContainerResolutionException(implementingType, CannotResolveAbstractType));
            }

            PopulateErrors(implementingType, ref errors);
            return(errors);
        }
Ejemplo n.º 2
0
        static void PopulateErrors(Type implementingType, ref ContainerResolutionErrorCollection errors)
        {
            var ctors = implementingType.GetConstructors();

            if (ctors.Length > 1)
            {
                errors.Add(implementingType, new ContainerResolutionException(implementingType, MultipleConstructors));
            }
            else if (ctors.Length == 0)
            {
                errors.Add(implementingType, new ContainerResolutionException(implementingType, NoPublicConstructors));
                return;
            }

            var ctor               = ctors.OrderByDescending(x => x.GetParameters().Length).FirstOrDefault();
            var parameters         = ctor.GetParameters();
            var parameterInstances = new List <object>();
            var container          = ContainerLocator.Current;

            foreach (var parameter in parameters)
            {
                try
                {
                    var defaultImplementingType   = IsConcreteType(parameter.ParameterType) ? parameter.ParameterType : null;
                    var parameterImplementingType = container.GetRegistrationType(parameter.ParameterType);
                    if (parameterImplementingType is null)
                    {
                        throw new ContainerResolutionException(parameter.ParameterType, MissingRegistration);
                    }

                    var instance = container.Resolve(parameter.ParameterType);
                    parameterInstances.Add(instance);
                }
                catch (Exception ex)
                {
                    // TODO: Add Exceptions Extensions lookup here to get root Exception
                    errors.Add(parameter.ParameterType, ex);
                    if (ex is ContainerResolutionException cre && !cre.IsKnownIssue)
                    {
                        foreach (var subError in cre.GetErrors())
                        {
                            errors.Add(subError.Key, subError.Value);
                        }
                    }
                }
            }

            // Return if we had an error with any children
            if (parameters.Length != parameterInstances.Count)
            {
                return;
            }

            try
            {
                // We generally expect some sort of InvokationException Exception here...
                ctor.Invoke(parameterInstances.ToArray());

                // If we managed to create an instance for every parameter and the
                // constructor didn't throw an exception when activating the instance
                // we really aren't sure what allowed us to get here...
                throw new ContainerResolutionException(implementingType, UnknownError);
            }
            catch (TargetInvocationException tie)
            {
                errors.Add(implementingType, tie);

                if (tie.InnerException != null)
                {
                    errors.Add(implementingType, tie.InnerException);
                }
            }
            catch (Exception ex)
            {
                errors.Add(implementingType, ex);
            }
        }