private void InitRequirements(ComponentRequirementMap map)
            {
                this.Requirements = new List <Type>();

                IEnumerable <RequiredComponentAttribute> attribs = this.Component.GetTypeInfo().GetAttributesCached <RequiredComponentAttribute>();

                foreach (RequiredComponentAttribute a in attribs)
                {
                    Type reqType = a.RequiredComponentType;

                    // Don't require itself
                    if (reqType == this.Component)
                    {
                        continue;
                    }

                    // Ignore invalid constraints
                    if (!this.IsValidRequirement(a))
                    {
                        continue;
                    }

                    this.Requirements.AddRange(map.GetRequirements(reqType).Where(t => !this.Requirements.Contains(t)));
                    if (!this.Requirements.Contains(reqType))
                    {
                        this.Requirements.Add(reqType);
                    }
                }
            }
            private void InitCreationChain(ComponentRequirementMap map)
            {
                this.CreationChain = new List <CreationChainItem>();

                IEnumerable <RequiredComponentAttribute> attributes = this.Component.GetTypeInfo().GetAttributesCached <RequiredComponentAttribute>();

                foreach (RequiredComponentAttribute attrib in attributes)
                {
                    // Ignore invalid constraints
                    if (!this.IsValidRequirement(attrib))
                    {
                        continue;
                    }

                    // If this is a conditional creation, add the sub-chain of the Component to create
                    if (attrib.CreateDefaultType != attrib.RequiredComponentType)
                    {
                        this.AddCreationChainElements(map, attrib, attrib.CreateDefaultType);
                    }

                    // In any case, add the sub-chain of direct requirements
                    this.AddCreationChainElements(map, attrib, attrib.RequiredComponentType);
                }

                // Remove any duplicates that we might have generated in the creation chain
                this.RemoveCreationChainDuplicates();
            }
            public void EnsureCreationChain(ComponentRequirementMap map)
            {
                if (this.initCreationChain == RecursiveInit.Initialized)
                {
                    return;
                }
                if (this.initCreationChain == RecursiveInit.InProgress)
                {
                    Logs.Core.WriteWarning(
                        "Detected a cyclic Component requirement in {0}. Requirements can not be ensured for cyclic dependencies.",
                        LogFormat.Type(this.Component));
                    return;
                }

                this.initCreationChain = RecursiveInit.InProgress;
                this.InitCreationChain(map);
                this.initCreationChain = RecursiveInit.Initialized;
            }
            private void AddCreationChainElements(ComponentRequirementMap map, RequiredComponentAttribute attrib, Type subChainType)
            {
                if (subChainType == this.Component)
                {
                    return;
                }

                int baseIndex      = this.CreationChain.Count;
                int subChainLength = 0;

                // Retrieve the creation sub-chain to satisfy this item's requirements
                List <CreationChainItem> createTypeSubChain = map.GetCreationChain(subChainType);

                foreach (CreationChainItem subItem in createTypeSubChain)
                {
                    this.CreationChain.Add(subItem);
                    subChainLength++;
                }

                // Add the main item after its requirement items so we're always creating bottom-up
                this.CreationChain.Add(new CreationChainItem
                {
                    RequiredType = attrib.RequiredComponentType,
                    CreateType   = attrib.CreateDefaultType
                });

                // If this is a conditional requirement, add a control item that checks the
                // requirement and skips this item and its sub-chains if it's already met.
                if (subChainLength > 0 && attrib.CreateDefaultType != attrib.RequiredComponentType)
                {
                    this.CreationChain.Insert(baseIndex, new CreationChainItem
                    {
                        RequiredType = attrib.RequiredComponentType,
                        SkipIfExists = 1 + subChainLength
                    });
                }
            }