public static bool UpdateNamedObjectsFromBaseType(INamedObjectContainer namedObjectContainer) { bool haveChangesOccurred = false; List <NamedObjectSave> referencedObjectsBeforeUpdate = new List <NamedObjectSave>(); for (int i = 0; i < namedObjectContainer.NamedObjects.Count; i++) { if (namedObjectContainer.NamedObjects[i].DefinedByBase) { referencedObjectsBeforeUpdate.Add(namedObjectContainer.NamedObjects[i]); } } List <NamedObjectSave> namedObjectsSetByDerived = new List <NamedObjectSave>(); List <NamedObjectSave> namedObjectsExposedInDerived = new List <NamedObjectSave>(); List <INamedObjectContainer> baseElements = new List <INamedObjectContainer>(); // June 1, 2011: // The following code // was using AddRange instead // of manually looping, but this // is only possible in .NET 4.0, and // GlueView still uses 3.1. // July 24, 2011 // Before today, this // code would loop through // all base Entities and search // for SetByDerived properties in // any NamedObjectSave. This caused // bugs. Basically if you had 3 Elements // in an inheritance chain and the one at the // very base defined a NOS to be SetByDerived, then // anything that inherited directly from the base should // be forced to define it. If it does, then the 3rd Element // in the inheritance chain shouldn't have to define it, but before // to day it did. This caused a lot of problems including generated // code creating the element twice. if (namedObjectContainer is EntitySave) { if (!string.IsNullOrEmpty(namedObjectContainer.BaseObject)) { baseElements.Add(ObjectFinder.Self.GetIElement(namedObjectContainer.BaseObject)); } //List<EntitySave> allBase = ((EntitySave)namedObjectContainer).GetAllBaseEntities(); //foreach (EntitySave baseEntitySave in allBase) //{ // baseElements.Add(baseEntitySave); //} } else { if (!string.IsNullOrEmpty(namedObjectContainer.BaseObject)) { baseElements.Add(ObjectFinder.Self.GetIElement(namedObjectContainer.BaseObject)); } //List<ScreenSave> allBase = ((ScreenSave)namedObjectContainer).GetAllBaseScreens(); //foreach (ScreenSave baseScreenSave in allBase) //{ // baseElements.Add(baseScreenSave); //} } foreach (INamedObjectContainer baseNamedObjectContainer in baseElements) { if (baseNamedObjectContainer != null) { namedObjectsSetByDerived.AddRange(baseNamedObjectContainer.GetNamedObjectsToBeSetByDerived()); namedObjectsExposedInDerived.AddRange(baseNamedObjectContainer.GetNamedObjectsToBeExposedInDerived()); } } #region See if there are any objects to be removed from the derived. for (int i = referencedObjectsBeforeUpdate.Count - 1; i > -1; i--) { bool contains = false; for (int j = 0; j < namedObjectsSetByDerived.Count; j++) { if (referencedObjectsBeforeUpdate[i].InstanceName == namedObjectsSetByDerived[j].InstanceName && referencedObjectsBeforeUpdate[i].DefinedByBase) { contains = true; break; } } for (int j = 0; j < namedObjectsExposedInDerived.Count; j++) { if (referencedObjectsBeforeUpdate[i].InstanceName == namedObjectsExposedInDerived[j].InstanceName && referencedObjectsBeforeUpdate[i].DefinedByBase) { contains = true; break; } } if (!contains) { NamedObjectSave nos = referencedObjectsBeforeUpdate[i]; string message = "The following object is marked as \"defined by base\" but it is not contained in " + "any base elements\n\n" + nos.ToString() + "\n\nWhat would you like to do?"; MultiButtonMessageBox mbmb = new MultiButtonMessageBox(); mbmb.MessageText = message; mbmb.AddButton("Remove " + nos.ToString(), DialogResult.Yes); mbmb.AddButton("Keep it, make it not \"defined by base\"", DialogResult.No); DialogResult result = mbmb.ShowDialog(); if (result == DialogResult.Yes) { // We got a NamedObject we should remove namedObjectContainer.NamedObjects.Remove(nos); referencedObjectsBeforeUpdate.RemoveAt(i); } else { nos.DefinedByBase = false; nos.InstantiatedByBase = false; } haveChangesOccurred = true; } } #endregion #region Next, see if there are any objects to be added for (int i = 0; i < namedObjectsSetByDerived.Count; i++) { NamedObjectSave namedObjectSetByDerived = namedObjectsSetByDerived[i]; NamedObjectSave matchingDefinedByBase = null;// contains = false; for (int j = 0; j < referencedObjectsBeforeUpdate.Count; j++) { if (referencedObjectsBeforeUpdate[j].InstanceName == namedObjectSetByDerived.InstanceName && referencedObjectsBeforeUpdate[j].DefinedByBase) { matchingDefinedByBase = referencedObjectsBeforeUpdate[j]; break; } } if (matchingDefinedByBase == null) { AddSetByDerivedNos(namedObjectContainer, namedObjectSetByDerived, false); } else { MatchDerivedToBase(namedObjectSetByDerived, matchingDefinedByBase); } } for (int i = 0; i < namedObjectsExposedInDerived.Count; i++) { NamedObjectSave namedObjectSetByDerived = namedObjectsExposedInDerived[i]; NamedObjectSave matchingDefinedByBase = null;// contains = false; for (int j = 0; j < referencedObjectsBeforeUpdate.Count; j++) { if (referencedObjectsBeforeUpdate[j].InstanceName == namedObjectSetByDerived.InstanceName && referencedObjectsBeforeUpdate[j].DefinedByBase) { matchingDefinedByBase = referencedObjectsBeforeUpdate[j]; break; } } if (matchingDefinedByBase == null) { AddSetByDerivedNos(namedObjectContainer, namedObjectSetByDerived, true); } else { MatchDerivedToBase(namedObjectSetByDerived, matchingDefinedByBase); } } #endregion return(haveChangesOccurred); }
private static MemberInfo GetMemberInfoForMember(NamedObjectSave namedObjectSave, string typeName, string variableToReset) { Type type = null; if (namedObjectSave.SourceType == SourceType.Entity) { type = typeof(PositionedObject); } else { type = TypeManager.GetTypeFromString(typeName); } if (type == null) { // this is an unknown type, so we should just return null; return null; } else { string firstVariable = variableToReset; bool shouldRecur = false; if (variableToReset.Contains('.')) { firstVariable = variableToReset.Substring(0, variableToReset.IndexOf('.')); shouldRecur = true; } MemberInfo[] memberInfoArray = type.GetMember(firstVariable); if (memberInfoArray.Length == 0) { throw new InvalidOperationException("Could not find any members with the name " + firstVariable + " in the NamedObject " + namedObjectSave.ToString() + " of type " + type); } MemberInfo memberInfo = memberInfoArray[0]; if (shouldRecur) { string typeOfMember = null; if (memberInfo is FieldInfo) { typeOfMember = ((FieldInfo)memberInfo).FieldType.Name; } else { typeOfMember = ((PropertyInfo)memberInfo).PropertyType.Name; } return GetMemberInfoForMember(namedObjectSave, typeOfMember, variableToReset.Substring(variableToReset.IndexOf('.') + 1)); } else { return memberInfo; } } }
private static string WriteMethodForClone(NamedObjectSave namedObject, ICodeBlock codeBlock, List<string[]> referencedFilesAlreadyUsingFullFile, AssetTypeInfo nosAti, string objectName, ReferencedFileSave rfs, IElement container, string containerName, string overridingName) { int lastParen = namedObject.SourceName.LastIndexOf(" ("); string nameOfSourceInContainer = namedObject.SourceName.Substring(0, lastParen); // This could have a quote in the name. If so we want to escape it since this will be put in code: nameOfSourceInContainer = nameOfSourceInContainer.Replace("\"", "\\\""); string cloneString = ".Clone()"; string namedObjectToPullFrom = null; foreach (string[] stringPair in referencedFilesAlreadyUsingFullFile) { if (rfs != null && stringPair[0] == rfs.Name && !namedObject.SourceName.StartsWith("Entire File (")) { namedObjectToPullFrom = stringPair[1]; break; } } // September 30, 2012 // Now all files - whether // they are part of an Entity // or part of a Screen, are static. // This means that the rfs.IsSharedStatic // check will usually fail. However, Screens // will still add to managers even for static // object, so we want to make sure that we don't // clone an object already added to managers, so we // need the last check to see if the container is a ScreenSave. if (nosAti == null || !nosAti.CanBeCloned || namedObjectToPullFrom != null || (rfs != null && rfs.IsSharedStatic == false) || container is ScreenSave) { cloneString = ""; } if (nosAti != null && !string.IsNullOrEmpty(nosAti.CustomCloneMethod)) { cloneString = nosAti.CustomCloneMethod; } AssetTypeInfo rfsAti = null; if (rfs != null) { rfsAti = rfs.GetAssetTypeInfo(); } bool usesFullConversion = false; if (rfsAti != null && rfsAti.Conversion.Count != 0) { var foundConversion = rfsAti.Conversion.FirstOrDefault(item => item.ToType == namedObject.InstanceType); if (foundConversion != null) { cloneString = foundConversion.ConversionPattern.Replace("{NEW}", objectName); cloneString = cloneString.Replace("{THIS}", rfs.GetInstanceName()); usesFullConversion = true; } } if (namedObjectToPullFrom != null) { containerName = namedObjectToPullFrom; } if (!string.IsNullOrEmpty(overridingName)) { containerName = overridingName; } string listMemberName = ContentParser.GetMemberNameForList(FileManager.GetExtension(namedObject.SourceFile), namedObject.InstanceType); if (!string.IsNullOrEmpty(listMemberName)) { listMemberName += "."; } if (nameOfSourceInContainer == "Entire File" && string.IsNullOrEmpty(listMemberName)) { if (usesFullConversion) { codeBlock.Line(cloneString + ";"); } else if (cloneString.Contains("{THIS}")) { string entireString = cloneString.Replace("{THIS}", objectName); entireString = entireString.Replace("{SOURCE_FILE}", containerName); codeBlock.Line(entireString); } else { codeBlock.Line(string.Format("{0} = {1}{2};", objectName, containerName, cloneString)); } } else { string findByNameLine = ""; if (nosAti != null) { findByNameLine = nosAti.FindByNameSyntax; if (string.IsNullOrEmpty(findByNameLine)) { string message = "The object " + namedObject.ToString() + " is part of a file. To be properly generated " + "the AssetTypeInfo (or CSV value) for " + nosAti.ToString() + " must contain a FindByNameSyntax property"; throw new Exception(message); } } findByNameLine = findByNameLine.Replace("OBJECTNAME", nameOfSourceInContainer); string possibleDot = "."; if (findByNameLine.StartsWith("[")) { possibleDot = ""; } //if (namedObject.AddToManagers) { // Not sure why we don't clone on a non add to manager. This post right here suggests we should // and I tend to believe Scott so...I'm following his advice: // http://www.flatredball.com/frb/forum/viewtopic.php?f=26&t=4741 codeBlock.Line(string.Format("{0} = {1}{2}{3}{4}{5};", objectName, containerName, possibleDot, listMemberName, findByNameLine, cloneString)); } //else //{ // stringBuilder.AppendLine( // string.Format("\t\t\t{0} = {1}{2}{3}{4};", // objectName, // containerName, // possibleDot, // listMemberName, // findByNameLine)); //} } return containerName; }
private static void CreateVariableResetField(NamedObjectSave namedObjectSave, string typeName, ICodeBlock codeBlock) { for (int i = 0; i < namedObjectSave.VariablesToReset.Count; i++) { string variableToReset = namedObjectSave.VariablesToReset[i]; string typeOfResetVariable = ""; MemberInfo memberInfo = null; try { memberInfo = GetMemberInfoForMember(namedObjectSave, typeName, variableToReset); } catch (InvalidOperationException) { // If we got here that means that the object doesn't have a variable matching what was passed in. // That's okay, we can just continue...well, after we tell the user about the problem. } if (memberInfo == null) { GlueGui.ShowMessageBox("Error generating code for " + namedObjectSave.ToString() + ":\nCould not find variable " + variableToReset + " in " + namedObjectSave.SourceClassType); } else { if (memberInfo is PropertyInfo) { typeOfResetVariable = TypeManager.ConvertToCommonType(((PropertyInfo)memberInfo).PropertyType.ToString()); } else { typeOfResetVariable = TypeManager.ConvertToCommonType(((FieldInfo)memberInfo).FieldType.ToString()); } // 1/2/2011 // The following // used to be protected // (instance) variable, but // this greatly bloats the size // of instances. I'm going to make // these variables static and we'll see // if this causes problems. codeBlock.Line(StringHelper.SpaceStrings("static", typeOfResetVariable, namedObjectSave.InstanceName) + variableToReset.Replace(".", "") + "Reset;"); } } }