Ejemplo n.º 1
0
        /// <summary>
        /// Recursively searches for repeating services in a auto-injection definition.
        /// </summary>
        /// <param name="serviceInterface">Registered interface to start the check on.</param>
        /// <param name="chainList">List of chain elements, that is filled by the method.</param>
        /// <returns><c>True</c>, if cyclic references have been found, <c>false</c> otherwise.</returns>
        private CircularityResult FindCircularAutoInjection(Type serviceInterface, IList <Type> chainList)
        {
            if (chainList.Contains(serviceInterface))
            {
                // The list already contains this service -> circular reference
                return(CircularityResult.Circularity);
            }
            else
            {
                chainList.Add(serviceInterface);
            }

            if (_serviceInfos.ContainsKey(serviceInterface))
            {
                IServiceInfo servInfo = _serviceInfos[serviceInterface];
                if (servInfo.AutoInjections != null)
                {
                    foreach (IAutoInjection injection in servInfo.AutoInjections)
                    {
                        List <Type> subChainList = new List <Type>(chainList);
                        if (injection.InjectFromAttachList)
                        {
                            if (_attachLists.ContainsKey(injection.BoundAttachList))
                            {
                                // Check all services in this AttachList
                                foreach (Type attachedService in _attachLists[injection.BoundAttachList])
                                {
                                    CircularityResult circularityResult = this.FindCircularAutoInjection(attachedService, subChainList);
                                    if (circularityResult != CircularityResult.NoErrors)
                                    {
                                        return(circularityResult);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // Check the bound service
                            CircularityResult circularityResult = this.FindCircularAutoInjection(injection.BoundService, subChainList);
                            if (circularityResult != CircularityResult.NoErrors)
                            {
                                return(circularityResult);
                            }
                        }
                    }
                }
            }
            else
            {
                return(CircularityResult.NotFoundError);
            }

            return(CircularityResult.NoErrors);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Checks the consistency of all service definitions and returns a list
        /// of faulty services with the error information that have been found for every service.
        /// </summary>
        /// <returns>
        /// Array of <see cref="ServiceInfoValidator.FaultyServiceInfo"/>
        /// objects, that contain information about faulty service definitions.
        /// </returns>
        public FaultyServiceInfo[] CheckServiceConsistency()
        {
            List <FaultyServiceInfo> faultyServices = new List <FaultyServiceInfo>();

            //try
            //{
            foreach (IServiceInfo serviceInfo in _serviceInfos.Values)
            {
                if ((serviceInfo.AutoInjections != null) && serviceInfo.AutoInjections.Any())
                {
                    // Search for circular injections (Service2 is injected into Service1, Service1 is injected into Service2 etc.)
                    List <Type>       chainList         = new List <Type>();
                    CircularityResult circularityResult = this.FindCircularAutoInjection(serviceInfo.ServiceInterface, chainList);
                    if (circularityResult == CircularityResult.Circularity)
                    {
                        // There is a circular reference somewhere
                        faultyServices.Add(new FaultyServiceInfo(ErrorReason.CircularAutoInjection,
                                                                 "The auto-injection definition for " + serviceInfo.ServiceInterface + " contains circular references.")
                                           );
                    }
                    else if (circularityResult == CircularityResult.NotFoundError)
                    {
                        // There is a circular reference somewhere
                        faultyServices.Add(new FaultyServiceInfo(ErrorReason.UnresolvedAutoInjection,
                                                                 "The auto-injection definition for " + serviceInfo.ServiceInterface + " contains unresolved references.")
                                           );
                    }

                    // Test constructor of implementing type
                    List <Type> ctorParams = new List <Type>();
                    foreach (IAutoInjection injection in serviceInfo.AutoInjections)
                    {
                        if (injection.InjectFromAttachList)
                        {
                            ctorParams.Add(injection.Interface.MakeArrayType());
                        }
                        else
                        {
                            ctorParams.Add(injection.Interface);
                        }
                    }

                    // Run through all constructors of the implementing type and look for a fitting one
                    bool foundCtor          = false;
                    ConstructorInfo[] ctors = serviceInfo.ServiceType.GetConstructors();
                    if (ctors != null)
                    {
                        for (int i = 0; i < ctors.Length; i++)
                        {
                            ParameterInfo[] parameters    = ctors[i].GetParameters();
                            int             minParamCount = 0;
                            if (ctorParams.Count < parameters.Length)
                            {
                                minParamCount = ctorParams.Count;
                            }
                            else
                            {
                                minParamCount = parameters.Length;
                            }
                            for (int j = minParamCount - 1; j >= 0; j--)
                            {
                                if (ctorParams[j].IsAssignableFrom(parameters[j].ParameterType))
                                {
                                    foundCtor = true;
                                }
                                else
                                {
                                    foundCtor = false;
                                    break;
                                }
                            }

                            if (foundCtor)
                            {
                                // We have found a fitting constructor, no more constructors are checked
                                break;
                            }
                        }
                    }

                    if (!foundCtor)
                    {
                        // Could not find an appropriate constructor for the auto-injection definition
                        faultyServices.Add(new FaultyServiceInfo(ErrorReason.NoConstructor,
                                                                 "The class implementing service " + serviceInfo.ServiceInterface.Name + " does not contain a constructor, that is needed to auto-inject other services.")
                                           );
                    }
                }
            }

            // Check all substitutes for integrity
            foreach (KeyValuePair <Type, Type> substEntry in _substitutions)
            {
                IServiceInfo newServInfo = this.GetServiceInfo(substEntry.Value);
                IServiceInfo oldServInfo = this.GetServiceInfo(substEntry.Key);
                if ((oldServInfo != null) && (newServInfo != null))
                {
                    //if (!oldServInfo.ServiceInterface.IsAssignableFrom(newServInfo.ServiceInterface))
                    //{
                    //  // The subtitutor does not implement the service interface of the substituted service
                    //  faultyServices.Add(new FaultyServiceInfo(NQErrorReason.SubstitutorInterfaceMismatch,
                    //      "The substituting service " + substEntry.Value + " does not implement the interface of the subtituted service " + substEntry.Key + ".")
                    //      );
                    //}

                    Type[] oldInterfaces = oldServInfo.ServiceType.GetInterfaces();
                    if ((oldInterfaces == null) || (oldInterfaces.Length == 0))
                    {
                        oldInterfaces = new Type[] { oldServInfo.ServiceType };
                    }

                    foreach (Type ifc in oldInterfaces)
                    {
                        if (!ifc.IsAssignableFrom(newServInfo.ServiceType))
                        {
                            // The subtitutor does not implement a service interface of the substituted servicefe
                            faultyServices.Add(new FaultyServiceInfo(ErrorReason.SubstitutorInterfaceMismatch,
                                                                     "The substituting service " + substEntry.Value + " does not implement all interfaces of the subtituted service " + substEntry.Key + ".")
                                               );
                        }
                    }
                }
            }

            // Check all substitution chains for cyclic references
            foreach (KeyValuePair <Type, Type> substEntry in _substitutions)
            {
                List <Type>       chainList         = new List <Type>();
                CircularityResult circularityResult = this.FindCircularSubstitution(substEntry.Value, chainList);
                if (circularityResult == CircularityResult.Circularity)
                {
                    // There is a circular reference somewhere
                    faultyServices.Add(new FaultyServiceInfo(ErrorReason.CircularSubstitution,
                                                             "The substitution chain for " + substEntry.Value + " contains circular references.")
                                       );
                }
            }

            //}
            //catch (Exception ex)
            //{
            //  string test = ex.Message;
            //}

            FaultyServiceInfo[] faultyServicesArray = new FaultyServiceInfo[faultyServices.Count];
            faultyServices.CopyTo(faultyServicesArray, 0);
            return(faultyServicesArray);
        }