Serializable Class with Nullable types to be able to tell if they are populated or not
        private static void UpdateObsoleteSettings(POCO.Config poco, POCO.ExtensionConfig pocoConfig, EarlyBoundGeneratorConfig @default)
        {
            if (new Version(poco.Version) < new Version("1.2016.6.1"))
            {
                // Storing of UnmappedProperties and EntityAttributeSpecified Names switched from Key,Value1,Value2|Key,Value1,Value2 to Key:Value1,Value2|Key:Value1,Value2
                // Also convert from a List to a HashSet
                pocoConfig.EntityAttributeSpecifiedNames = ConvertNonColonDelimitedDictionaryListToDictionaryHash(pocoConfig.EntityAttributeSpecifiedNames);
                pocoConfig.UnmappedProperties            = ConvertNonColonDelimitedDictionaryListToDictionaryHash(pocoConfig.UnmappedProperties);
            }

            if (new Version(poco.Version) < new Version("1.2018.9.12"))
            {
                // Update the OptionSet codecustomization Argument Setting to use the new Generic Code Customziation Service
                var oldValue = poco.ExtensionArguments.FirstOrDefault(
                    a => a.SettingType == CreationType.OptionSets &&
                    a.Name == "codecustomization");
                var newValue = @default.ExtensionArguments.FirstOrDefault(
                    a => a.SettingType == CreationType.OptionSets &&
                    a.Name == "codecustomization");
                if (oldValue != null &&
                    newValue != null)
                {
                    poco.ExtensionArguments.Remove(oldValue);
                    poco.ExtensionArguments.Add(newValue);
                }
            }
        }
        /// <summary>
        /// Updates properties, only if actually populated in the poco.
        /// </summary>
        /// <param name="poco"></param>
        public void SetPopulatedValues(POCO.ExtensionConfig poco)
        {
            ActionPrefixesToSkip                = GetValueOrDefault(poco.ActionPrefixesToSkip, ActionPrefixesToSkip);
            ActionPrefixesWhitelist             = GetValueOrDefault(poco.ActionPrefixesWhitelist, ActionPrefixesWhitelist);
            ActionsWhitelist                    = GetValueOrDefault(poco.ActionsWhitelist, ActionsWhitelist);
            ActionsToSkip                       = GetValueOrDefault(poco.ActionsToSkip, ActionsToSkip);
            AddDebuggerNonUserCode              = poco.AddDebuggerNonUserCode ?? AddDebuggerNonUserCode;
            AddNewFilesToProject                = poco.AddNewFilesToProject ?? AddNewFilesToProject;
            AddOptionSetMetadataAttribute       = poco.AddOptionSetMetadataAttribute ?? AddOptionSetMetadataAttribute;
            CamelCaseClassNames                 = poco.CamelCaseClassNames ?? CamelCaseClassNames;
            CamelCaseMemberNames                = poco.CamelCaseMemberNames ?? CamelCaseMemberNames;
            CreateOneFilePerAction              = poco.CreateOneFilePerAction ?? CreateOneFilePerAction;
            CreateOneFilePerEntity              = poco.CreateOneFilePerEntity ?? CreateOneFilePerEntity;
            CreateOneFilePerOptionSet           = poco.CreateOneFilePerOptionSet ?? CreateOneFilePerOptionSet;
            DeleteFilesFromOutputFolders        = poco.DeleteFilesFromOutputFolders ?? DeleteFilesFromOutputFolders;
            EntitiesToSkip                      = GetValueOrDefault(poco.EntitiesToSkip, EntitiesToSkip);
            EntitiesWhitelist                   = GetValueOrDefault(poco.EntitiesWhitelist, EntitiesWhitelist);
            EntityAttributeSpecifiedNames       = GetValueOrDefault(poco.EntityAttributeSpecifiedNames, EntityAttributeSpecifiedNames);
            EntityPrefixesToSkip                = GetValueOrDefault(poco.EntityPrefixesToSkip, EntityPrefixesToSkip);
            EntityPrefixesWhitelist             = GetValueOrDefault(poco.EntityPrefixesWhitelist, EntityPrefixesWhitelist);
            FilePrefixText                      = GetValueOrDefault(poco.FilePrefixText, FilePrefixText);
            GenerateActionAttributeNameConsts   = poco.GenerateActionAttributeNameConsts ?? GenerateActionAttributeNameConsts;
            GenerateAttributeNameConsts         = poco.GenerateAttributeNameConsts ?? GenerateAttributeNameConsts;
            GenerateAnonymousTypeConstructor    = poco.GenerateAnonymousTypeConstructor ?? GenerateAnonymousTypeConstructor;
            GenerateConstructorsSansLogicalName = poco.GenerateConstructorsSansLogicalName ?? GenerateConstructorsSansLogicalName;
            GenerateEntityRelationships         = poco.GenerateEntityRelationships ?? GenerateEntityRelationships;
            GenerateEntityTypeCode              = poco.GenerateEntityTypeCode ?? GenerateEntityTypeCode;
            GenerateEnumProperties              = poco.GenerateEnumProperties ?? GenerateEnumProperties;
            GenerateOnlyReferencedOptionSets    = poco.GenerateOnlyReferencedOptionSets ?? GenerateOnlyReferencedOptionSets;
            GenerateOptionSetMetadataAttribute  = poco.GenerateOptionSetMetadataAttribute ?? GenerateOptionSetMetadataAttribute;
            GroupLocalOptionSetsByEntity        = poco.GroupLocalOptionSetsByEntity ?? GroupLocalOptionSetsByEntity;
            InvalidCSharpNamePrefix             = poco.InvalidCSharpNamePrefix ?? InvalidCSharpNamePrefix;
            MakeAllFieldsEditable               = poco.MakeAllFieldsEditable ?? MakeAllFieldsEditable;
            MakeReadonlyFieldsEditable          = poco.MakeReadonlyFieldsEditable ?? MakeReadonlyFieldsEditable;
            MakeResponseActionsEditable         = poco.MakeResponseActionsEditable ?? MakeResponseActionsEditable;
            LocalOptionSetFormat                = poco.LocalOptionSetFormat ?? LocalOptionSetFormat;
            OptionSetLanguageCodeOverride       = poco.OptionSetLanguageCodeOverride ?? OptionSetLanguageCodeOverride;
            OptionSetNames                      = GetValueOrDefault(poco.OptionSetNames, OptionSetNames);
            OptionSetPrefixesToSkip             = GetValueOrDefault(poco.OptionSetPrefixesToSkip, OptionSetPrefixesToSkip);
            OptionSetsToSkip                    = GetValueOrDefault(poco.OptionSetsToSkip, OptionSetsToSkip);
            ProjectNameForEarlyBoundFiles       = poco.ProjectNameForEarlyBoundFiles ?? ProjectNameForEarlyBoundFiles;
            PropertyEnumMappings                = GetValueOrDefault(poco.PropertyEnumMappings, PropertyEnumMappings);
            ReadSerializedMetadata              = poco.ReadSerializedMetadata ?? ReadSerializedMetadata;
            RemoveRuntimeVersionComment         = poco.RemoveRuntimeVersionComment ?? RemoveRuntimeVersionComment;
            ReplaceOptionSetPropertiesWithEnum  = poco.ReplaceOptionSetPropertiesWithEnum ?? ReplaceOptionSetPropertiesWithEnum;
            SerializeMetadata                   = poco.SerializeMetadata ?? SerializeMetadata;
            TokenCapitalizationOverrides        = GetValueOrDefault(poco.TokenCapitalizationOverrides, TokenCapitalizationOverrides);
            UnmappedProperties                  = GetValueOrDefault(poco.UnmappedProperties, UnmappedProperties);
            UseDeprecatedOptionSetNaming        = poco.UseDeprecatedOptionSetNaming ?? UseDeprecatedOptionSetNaming;
            UseLogicalNames                     = poco.UseLogicalNames ?? UseLogicalNames;
            UseTfsToCheckoutFiles               = poco.UseTfsToCheckoutFiles ?? UseTfsToCheckoutFiles;
            WaitForAttachedDebugger             = poco.WaitForAttachedDebugger ?? WaitForAttachedDebugger;

            string GetValueOrDefault(string value, string defaultValue)
            {
                return(string.IsNullOrWhiteSpace(value) ? defaultValue : value);
            }
        }
        private static void UpdateObsoleteSettings(POCO.Config poco, POCO.ExtensionConfig pocoConfig, EarlyBoundGeneratorConfig @default)
        {
            var pocoVersion = new Version(poco.Version);

            if (pocoVersion < new Version("1.2016.6.1"))
            {
                // Storing of UnmappedProperties and EntityAttributeSpecified Names switched from Key,Value1,Value2|Key,Value1,Value2 to Key:Value1,Value2|Key:Value1,Value2
                // Also convert from a List to a HashSet
                pocoConfig.EntityAttributeSpecifiedNames = ConvertNonColonDelimitedDictionaryListToDictionaryHash(pocoConfig.EntityAttributeSpecifiedNames);
                pocoConfig.UnmappedProperties            = ConvertNonColonDelimitedDictionaryListToDictionaryHash(pocoConfig.UnmappedProperties);
            }

            if (pocoVersion < new Version("1.2018.9.12"))
            {
                // Update the OptionSet codecustomization Argument Setting to use the new Generic Code Customization Service
                var oldValue = poco.ExtensionArguments.FirstOrDefault(
                    a => a.SettingType == CreationType.OptionSets &&
                    a.Name == "codecustomization");
                var newValue = @default.ExtensionArguments.FirstOrDefault(
                    a => a.SettingType == CreationType.OptionSets &&
                    a.Name == "codecustomization");
                if (oldValue != null &&
                    newValue != null)
                {
                    poco.ExtensionArguments.Remove(oldValue);
                    poco.ExtensionArguments.Add(newValue);
                }
            }

            if (pocoVersion < new Version("1.2020.3.23"))
            {
                // Added new option to overwrite Option Set properties.  This is the desired default now, but don't break old generation settings.
                if (poco.ExtensionConfig.ReplaceOptionSetPropertiesWithEnum == null)
                {
                    poco.ExtensionConfig.ReplaceOptionSetPropertiesWithEnum = false;
                }
            }

            if (pocoVersion < new Version("1.2020.10.1"))
            {
                // Issue #254 add invalid actions to blacklist.
                var invalidBlacklistItems = "RetrieveAppSettingList|RetrieveAppSetting|SaveAppSetting|msdyn_GetSIFeatureConfiguration".ToLower();
                if (string.IsNullOrWhiteSpace(poco.ExtensionConfig.ActionsToSkip))
                {
                    poco.ExtensionConfig.ActionsToSkip = invalidBlacklistItems;
                }
                else
                {
                    poco.ExtensionConfig.ActionsToSkip += "|" + invalidBlacklistItems;
                }
            }

            if (pocoVersion < new Version("1.2020.12.18"))
            {
                // 12.18.2020 introduced Valueless parameters, but GenerateActions existed before as a null, need a boolean value to determine if it should be included
                var generateActions = poco.UserArguments.FirstOrDefault(a => a.Name == UserArgumentNames.GenerateActions && a.Value == null);
                if (generateActions != null)
                {
                    generateActions.Value     = "true";
                    generateActions.Valueless = true;
                }
            }
        }