/// <summary> /// Given the specified target <see cref="GameObject"/> and <see cref="Component"/> type, /// this method enumerates all <see cref="Component"/> types that will have to be created /// on the target object in order to satisfy its requirements. The result will be sorted /// in order of creation. /// </summary> /// <param name="targetObj"></param> /// <param name="targetComponentType"></param> /// <returns></returns> public IEnumerable <Type> GetRequirementsToCreate(GameObject targetObj, Type targetComponentType) { // Retrieve the component's requirements TypeData data; if (!this.typeDataCache.TryGetValue(targetComponentType, out data)) { data = new TypeData(targetComponentType); this.typeDataCache[targetComponentType] = data; } data.EnsureCreationChain(this); // Create a sorted list of all components that need to be instantiated // in order to satisfy the requirements for adding the given component to // the specified object. List <Type> createList = new List <Type>(data.CreationChain.Count); for (int i = 0; i < data.CreationChain.Count; i++) { CreationChainItem item = data.CreationChain[i]; if (targetObj.GetComponent(item.RequiredType) != null) { i += item.SkipIfExists; continue; } if (item.CreateType != null && !createList.Contains(item.CreateType)) { createList.Add(item.CreateType); } } return(createList); }
private void RemoveCreationChainDuplicates() { // We'll iterate over the creation chain assuming that each item // is found to be already existing (so we can't assume to have created // any specific type for abstract and interface requirements). List <TypeInfo> guaranteedTypes = new List <TypeInfo>(); int uncertainCounter = 0; int parentIndex = -1; for (int i = 0; i < this.CreationChain.Count; i++) { // Can we guarantee that all requirements of this item will have been met? TypeInfo requriedTypeInfo = this.CreationChain[i].RequiredType.GetTypeInfo(); bool requirementMet = guaranteedTypes.Any(t => requriedTypeInfo.IsAssignableFrom(t)); // If yes, remove the item and its sub-chains if (requirementMet) { int removeCount = 1 + this.CreationChain[i].SkipIfExists; this.CreationChain.RemoveRange(i, removeCount); if (uncertainCounter > 0) { CreationChainItem parentItem = this.CreationChain[parentIndex]; parentItem.SkipIfExists -= removeCount; this.CreationChain[parentIndex] = parentItem; uncertainCounter -= removeCount; } i--; } // Otherwise, proceed to the next item else { if (uncertainCounter == 0) { // If this item will create a Component, we can guarantee that its requirement is met if (this.CreationChain[i].CreateType != null) { guaranteedTypes.Add(requriedTypeInfo); } // If this item might skip followup items, only allow to assume that the very last // item's requirement will have been met, since after that one we can be sure that // it was either there all along or was now created. uncertainCounter += Math.Max(0, this.CreationChain[i].SkipIfExists - 1); parentIndex = i; } else { uncertainCounter--; } } } }