Ejemplo n.º 1
0
 public static bool TryConstruct(
     Type targetType,
     out object service,
     ServiceConstructorRequest request,
     IServiceRegistrationProvider serviceProvider,
     Func <Type, object> instanceProvider = null,
     bool tryConstructArguments           = false,
     bool?requireConstructorAttributes    = null,
     IReadOnlyCollection <Type> constructorAttributeTypes = null)
 {
     if (targetType == null)
     {
         throw new ArgumentNullException(nameof(targetType));
     }
     if (request == null)
     {
         throw new ArgumentNullException(nameof(request));
     }
     if (serviceProvider == null)
     {
         throw new ArgumentNullException(nameof(serviceProvider));
     }
     if ((constructorAttributeTypes == null) ||
         (constructorAttributeTypes.Count == 0))
     {
         constructorAttributeTypes = new[] { typeof(ServiceProviderConstructorAttribute) }
     }
     ;
     if (request.ConstructingTypes.Contains(targetType))
     {
         request.TraceStack.Add(
             "Found a recursive constructor dependency"
             + $": '{targetType.GetFriendlyFullName()}'"
             + " ... cannot continue.");
         service = null;
         return(false);
     }
     request.ConstructingTypes.Add(targetType);
     request.Logger.Verbose("Constructing {0}.", targetType.GetFriendlyFullName());
     if (ServiceConstructorMethods.invokeMember(
             ServiceConstructorMethods.findConstructors(
                 targetType,
                 requireConstructorAttributes,
                 constructorAttributeTypes,
                 request.TraceStack),
             false,
             null,
             out service,
             request,
             serviceProvider,
             instanceProvider,
             tryConstructArguments,
             requireConstructorAttributes,
             constructorAttributeTypes,
             false))
     {
         request.Logger.Verbose(
             "Construct result for '{0}' is true: '{1}'.",
             targetType.GetFriendlyFullName(),
             service.GetType().GetFriendlyFullName());
         request.ConstructingTypes.Remove(targetType);
         return(true);
     }
     request.Logger.Warning("Construct result for '{0}' is false.", targetType.GetFriendlyFullName());
     request.ConstructingTypes.Remove(targetType);
     return(false);
 }
Ejemplo n.º 2
0
        private static bool invokeMember(
            IEnumerable <MethodBase> members,
            bool isMethod,
            object methodTarget,
            out object newInstance,
            ServiceConstructorRequest request,
            IServiceRegistrationProvider serviceProvider,
            Func <Type, object> instanceProvider,
            bool tryConstructArguments,
            bool?requireConstructorAttributes,
            IReadOnlyCollection <Type> constructorAttributeTypes,
            bool isRecursed)
        {
            newInstance = null;
            bool success = false;

            foreach (MethodBase methodBase in members)
            {
                ParameterInfo[] parameters = methodBase.GetParameters();
                if (parameters.Length == 0)
                {
                    success = isMethod
                                                        ? ServiceConstructorMethods.tryInvokeMethod(
                        methodTarget,
                        (MethodInfo)methodBase,
                        new object[0],
                        request.TraceStack)
                                                        : ServiceConstructorMethods.tryInvokeConstructor(
                        (ConstructorInfo)methodBase,
                        new object[0],
                        out newInstance,
                        request.TraceStack);
                    break;
                }
                List <object> arguments = new List <object>(parameters.Length);
                foreach (ParameterInfo parameterInfo in parameters)
                {
                    if (ServiceConstructorMethods.tryResolve(
                            parameterInfo.ParameterType,
                            out object parameterResult,
                            request,
                            serviceProvider,
                            instanceProvider,
                            !tryConstructArguments))
                    {
                        arguments.Add(parameterResult);
                        continue;
                    }
                    if (tryConstructArguments)
                    {
                        if (request.ConstructingTypes.Contains(parameterInfo.ParameterType))
                        {
                            request.TraceStack.Add(
                                "Found a recursive constructor dependency"
                                + $": '{parameterInfo.ParameterType.GetFriendlyFullName()}'"
                                + " ... cannot continue.");
                            break;
                        }
                        request.ConstructingTypes.Add(parameterInfo.ParameterType);
                        bool argumentSuccess
                            = ServiceConstructorMethods.invokeMember(
                                  ServiceConstructorMethods.findConstructors(
                                      parameterInfo.ParameterType,
                                      requireConstructorAttributes,
                                      constructorAttributeTypes,
                                      request.TraceStack),
                                  false,
                                  null,
                                  out object argumentResult,
                                  request,
                                  serviceProvider,
                                  instanceProvider,
                                  true,
                                  requireConstructorAttributes,
                                  constructorAttributeTypes,
                                  true);
                        request.ConstructingTypes.Remove(parameterInfo.ParameterType);
                        if (argumentSuccess)
                        {
                            arguments.Add(argumentResult);
                            continue;
                        }
                    }
                    if (parameterInfo.HasDefaultValue)
                    {
                        request.TraceStack.Add(
                            $"Parameter '{parameterInfo.ParameterType.GetFriendlyFullName()}' has default value.");
                        arguments.Add(parameterInfo.DefaultValue);
                    }
                    else
                    {
                        break;
                    }
                }
                if ((arguments.Count != parameters.Length) ||
                    (isMethod
                                                                ? !ServiceConstructorMethods.tryInvokeMethod(
                         methodTarget,
                         (MethodInfo)methodBase,
                         arguments.ToArray(),
                         request.TraceStack)
                                                                : !ServiceConstructorMethods.tryInvokeConstructor(
                         (ConstructorInfo)methodBase,
                         arguments.ToArray(),
                         out newInstance,
                         request.TraceStack)))
                {
                    continue;
                }
                request.Dependencies.TryAddRange(
                    methodBase.DeclaringType,
                    parameters.Select(parameter => parameter.ParameterType));
                success = true;
                break;
            }
            if (isRecursed)
            {
                return(success);
            }
            if (success)
            {
                if (request.Logger.IsVerbose())
                {
                    request.Logger.Verbose(GetTraceMessage());
                }
            }
            else
            {
                if (request.Logger.IsInfo())
                {
                    request.Logger.Info(GetTraceMessage());
                }
            }
            string GetTraceMessage()
            {
                string        separator = $"{Environment.NewLine}    ";
                StringBuilder sb        = request.TraceStack.ToConcatenatedString(null, separator);

                if (sb.Length != 0)
                {
                    sb.Insert(0, "    ");
                }
                return(sb.ToString());
            }

            return(success);
        }