private IEnumerable <MemberResolutionInfo> DoIdentifyUnresolvedMembers() { //Since not everything is serialized, e.g. null values, we cannot simply get the first element of a specific type and use that, //we have to get the union of all fields that are serialized across all elements of that type. var typeElements = from doc in _stagedAis from el in doc.Descendants <StageElement>() let type = el.Attribute("type") where type != null group el by type.value into typeGroup select new { type = typeGroup.Key, members = (from el in typeGroup from m in el.Items() let name = m.name orderby name group m by m.name into memberGroup select new { name = memberGroup.Key, items = memberGroup.ToArray() }) }; //Next we check that each member found actually exists on the type. MemberResolutionInfo memberInfo = new MemberResolutionInfo(); foreach (var t in typeElements.OrderBy(t => t.type)) { var typeName = t.type; var type = Type.GetType(typeName, false); //This can still happen since the user can have opted to not resolve a type and it will be removed later. if (type == null) { continue; } //Check fields and properties var fieldsAndPropNames = SerializationMaster.GetSerializedFields(type).Select(f => f.Name).Concat(SerializationMaster.GetSerializedProperties(type).Select(p => p.Name)).ToArray(); foreach (var m in t.members) { if (!fieldsAndPropNames.Contains(m.name, StringComparer.Ordinal)) { memberInfo.unresolvedMembers.Add( new Member { unresolvedName = m.name, items = m.items }); } else { memberInfo.validMappedMembers.Add(m.name); } } //There is no need to new up various instances if no unresolved members are found, so we do it this way if (memberInfo.unresolvedMembers.Count > 0) { memberInfo.type = type; memberInfo.typeName = new TypeNameTokens(typeName); yield return(memberInfo); memberInfo = new MemberResolutionInfo(); } else { memberInfo.validMappedMembers.Clear(); } } }
private void Investigate(AIStorage[] ais) { var availableTypes = from t in ApexReflection.GetRelevantTypes() where !t.IsAbstract && (!_excludeApexTypes || t.Namespace == null || !t.Namespace.StartsWith("Apex.AI")) && (t.IsDefined <ApexSerializedTypeAttribute>(true) || SerializationMaster.GetSerializedProperties(t).Any() || SerializationMaster.GetSerializedFields(t).Any()) orderby t.FullName select new TypeNameTokens(t.AssemblyQualifiedName); var aiLookup = new Dictionary <string, ReferencingAI>(StringComparer.Ordinal); foreach (var ai in ais) { aiLookup.Add(ai.aiId, new ReferencingAI(ai.name)); } _referencedTypes.Clear(); _unreferencedTypes.Clear(); foreach (var t in availableTypes) { var refType = new ReferencedType(t.fullTypeName); foreach (var ai in ais) { if (ai.configuration.Contains(t.completeTypeName)) { var refAI = aiLookup[ai.aiId]; refAI.referencedTypes.Add(refType); refType.referencingAIs.Add(refAI); } } if (refType.referencingAIs.Count > 0) { _referencedTypes.Add(refType); } else { _unreferencedTypes.Add(t); } } _referencingAIs = (from ai in aiLookup.Values where ai.referencedTypes.Count > 0 orderby ai.name select ai).ToArray(); _step = Step.Result; _owner.Repaint(); }