When working with Entity Framework, is it possible to force generated entity classes to be Pascal case?

后端 未结 3 1417
一生所求
一生所求 2021-01-16 20:54

The database I\'m working against has table names such as \"table_name\". That\'s fine, but I\'d like to generate classes in the format \"TableName\" to work with in C#, Pas

相关标签:
3条回答
  • 2021-01-16 21:02

    Update: For use with EF6, see additional answer on this page.

    Thanks to Alex's answer, I've now extended this code to a full working solution that solves this problem. Since it's taken me most of the day, I'm posting here to help others facing the same challenge. This includes a complete class for manipulating the edmx file (no points for pretty code here) which passes fairly verbose unit tests on varying input strings:

    A few examples:

    some_class > SomeClass

    _some_class_ > SomeClass

    some_1_said > Some1Said

    I had some additional issues to deal with:

    Firstly optionally not replacing underscores while still changing the string to pascal case (due to column names like "test_string" and "teststring", which both resolved to "TestString" otherwise, causing collisions).

    Secondly, my code here takes an input parameter that modifies the object context class name that is generated.

    Lastly, I wasn't initially sure how to get the designer file to update after modifiying the edmx, so I've included exact steps. I would recommend creating a pre build step in Visual Studio, which saves some of the remaining effort in updating from a modified database schema.

    Updating an EDMX File to Reflect Database Changes

    1. Double click the edmx file to show the design surface.

    2. Right click the design surface and select "update model from database".

    3. Select "yes include sensitive information in connection string".

    4. Uncheck "save entity connection settings in App Config" (we already have these).

    5. Select the appropriate database. In Add screen select Tables, Views etc.

    6. Leave pluralise and foreign key options as checked. If creating the edmx file from fresh, you are given the option to enter a model name. You can change or leave this.

    7. Click finish.

    8. Run the code below on the edmx file.

    9. Depending on the state of the application, you may see errors here until the next step.

    10. Right click the edmx file that you are updating, and select "Run custom tool" in Visual Studio. This will cuse the designer.cs (C#) file to be updated.

    11. Run build to check there are no compiler errors.

    12. Run tests to ensure application is functioning correctly.

    13. Any application issues following this should be expected according to the application changes that have been made.

    Replacing an edmx file in it's entirety.

    1. Delete the edmx file, taking the designer file with it.

    2. Right click the entities folder

    3. From the create file dialogue, select ADO.NET Entity Data Model. Name it accroding to the class name you would like for your object context(IMPORTANT). This value is referenced in the connection string, so take a look at your app config in case of issues.

    4. In choose model contents, select generate from database.

    5. Follow above instructions from step 3.

      using System;    
      using System.IO;    
      using System.Linq;    
      using System.Text;    
      using System.Xml;    
      using System.Xml.Linq;
      
      namespace EdmxStringFormatter
      {
          public class Program
          {
              static void Main(string[] args)
              {
                  if (args.Length < 1) return;
      
              string filePath = args[0];
      
              string entityName = null;
      
              // Optionally do not replace underscores which 
              // helps with naming collisions with siimilarly named
              // columns on some database tables.
      
              bool replaceUnderscores = true;
      
              // Allow for the replacement of the object context class name, which is useful
              // where multiple databases have edmx files.
      
              bool doEntityNameReplace = false;
      
              if (args.Length > 1)
              {
                  entityName = args[1];
                  doEntityNameReplace = true;
              }
      
              if (args.Length > 2)
              {
                  replaceUnderscores = args[2] != "0";
              }
      
              if (!File.Exists(filePath))
              {
                  StopWithMessage("Could not find specified file.");
                  return;
              }
              if (Path.GetExtension(filePath) != ".edmx")
              {
                  StopWithMessage("This works only on EDMX files.");
                  return;
              }
      
              // Processing:
      
              Console.WriteLine("Creating backup: " + Path.ChangeExtension(filePath, ".bak"));
              File.Copy(filePath, Path.ChangeExtension(filePath, ".bak"), true);
      
              Console.WriteLine("Reading target document...");
      
              XDocument xdoc = XDocument.Load(filePath);
      
              const string CSDLNamespace = "http://schemas.microsoft.com/ado/2008/09/edm";
              const string MSLNamespace = "http://schemas.microsoft.com/ado/2008/09/mapping/cs";
              const string DiagramNamespace = "http://schemas.microsoft.com/ado/2008/10/edmx";
      
              const string CSNameSpace = "http://schemas.microsoft.com/ado/2008/09/mapping/cs";
      
              XElement csdl = xdoc.Descendants(XName.Get("Schema", CSDLNamespace)).First();
              XElement msl = xdoc.Descendants(XName.Get("Mapping", MSLNamespace)).First();
              XElement designerDiagram = xdoc.Descendants(XName.Get("Diagram", DiagramNamespace)).First();
      
              //modifications for renaming everything, not just table names:
      
              #region CSDL2
      
              Console.WriteLine("Modifying CSDL...");
              Console.WriteLine(" - modifying entity sets...");
      
              foreach (var entitySet in csdl.Element(XName.Get("EntityContainer", CSDLNamespace)).Elements(XName.Get("EntitySet", CSDLNamespace)))
              {
                  entitySet.Attribute("Name").Value = FormatString(entitySet.Attribute("Name").Value, replaceUnderscores);
                  entitySet.Attribute("EntityType").Value = FormatString(entitySet.Attribute("EntityType").Value, replaceUnderscores);
              }
      
              Console.WriteLine(" - modifying association sets...");
              foreach (var associationSet in csdl.Element(XName.Get("EntityContainer", CSDLNamespace)).Elements(XName.Get("AssociationSet", CSDLNamespace)))
              {
                  foreach (var end in associationSet.Elements(XName.Get("End", CSDLNamespace)))
                  {
                      end.Attribute("EntitySet").Value = FormatString(end.Attribute("EntitySet").Value, replaceUnderscores);
                  }
              }
      
              Console.WriteLine(" - modifying entity types...");
              foreach (var entityType in csdl.Elements(XName.Get("EntityType", CSDLNamespace)))
              {
                  entityType.Attribute("Name").Value = FormatString(entityType.Attribute("Name").Value, replaceUnderscores);
      
                  foreach (var key in entityType.Elements(XName.Get("Key", CSDLNamespace)))
                  {
                      foreach (var propertyRef in key.Elements(XName.Get("PropertyRef", CSDLNamespace)))
                      {
                          propertyRef.Attribute("Name").Value = FormatString(propertyRef.Attribute("Name").Value, replaceUnderscores);
                      }
                  }
      
                  foreach (var property in entityType.Elements(XName.Get("Property", CSDLNamespace)))
                  {
                      property.Attribute("Name").Value = FormatString(property.Attribute("Name").Value, replaceUnderscores);
                  }
      
                  foreach (var navigationProperty in entityType.Elements(XName.Get("NavigationProperty", CSDLNamespace)))
                  {
                      navigationProperty.Attribute("Name").Value = FormatString(navigationProperty.Attribute("Name").Value, replaceUnderscores);
                  }
      
              }
      
              Console.WriteLine(" - modifying associations...");
              foreach (var association in csdl.Elements(XName.Get("Association", CSDLNamespace)))
              {
                  foreach (var end in association.Elements(XName.Get("End", CSDLNamespace)))
                  {
                      end.Attribute("Type").Value = FormatString(end.Attribute("Type").Value, replaceUnderscores);
                  }
                  foreach (var propref in association.Descendants(XName.Get("PropertyRef", CSDLNamespace)))
                  {
                      //propertyrefs are contained in constraints
                      propref.Attribute("Name").Value = FormatString(propref.Attribute("Name").Value, replaceUnderscores);
                  }
              }
      
              #endregion
      
              #region MSL2
      
              Console.WriteLine("Modifying MSL...");
              Console.WriteLine(" - modifying entity set mappings...");
      
              foreach (var entitySetMapping in msl.Element(XName.Get("EntityContainerMapping", MSLNamespace)).Elements(XName.Get("EntitySetMapping", MSLNamespace)))
              {
                  entitySetMapping.Attribute("Name").Value = FormatString(entitySetMapping.Attribute("Name").Value, replaceUnderscores);
      
                  foreach (var entityTypeMapping in entitySetMapping.Elements(XName.Get("EntityTypeMapping", MSLNamespace)))
                  {
                      entityTypeMapping.Attribute("TypeName").Value = FormatString(entityTypeMapping.Attribute("TypeName").Value, replaceUnderscores);
                      foreach
                      (var scalarProperty in
                      (entityTypeMapping.Element(XName.Get("MappingFragment", MSLNamespace))).Elements(XName.Get("ScalarProperty", MSLNamespace))
                      )
                      {
                          scalarProperty.Attribute("Name").Value = FormatString(scalarProperty.Attribute("Name").Value, replaceUnderscores);
                      }
                  }
              }
      
              Console.WriteLine(" - modifying association set mappings...");
      
              foreach (var associationSetMapping in msl.Element(XName.Get("EntityContainerMapping", MSLNamespace)).Elements(XName.Get("AssociationSetMapping", MSLNamespace)))
              {
                  foreach (var endProperty in associationSetMapping.Elements(XName.Get("EndProperty", MSLNamespace)))
                  {
                      foreach (var scalarProperty in endProperty.Elements(XName.Get("ScalarProperty", MSLNamespace)))
                      {
                          scalarProperty.Attribute("Name").Value = FormatString(scalarProperty.Attribute("Name").Value, replaceUnderscores);
                      }
                  }
              }
              #endregion
      
      
              #region Designer
      
              Console.WriteLine("Modifying designer content...");
              foreach (var item in designerDiagram.Elements(XName.Get("EntityTypeShape", DiagramNamespace)))
              {
                  item.Attribute("EntityType").Value = FormatString(item.Attribute("EntityType").Value, replaceUnderscores);
              }
      
              #endregion
      
              // Optionally replace the entity name in case the default of "Entity" is not
              // sufficient for your needs.
      
              if (doEntityNameReplace)
              {
                  Console.WriteLine("Modifying entity name refs...");
      
                  // CSDL
                  xdoc.Descendants(XName.Get("EntityContainer", CSDLNamespace)).First().Attribute("Name").Value = entityName;
      
                  // Diagram 
                  xdoc.Descendants(XName.Get("Diagram", DiagramNamespace)).First().Attribute("Name").Value = entityName;
      
                  // Diagram 
                  xdoc.Descendants(XName.Get("EntityContainerMapping", CSNameSpace)).First().Attribute("CdmEntityContainer").Value = entityName;
              }
      
              Console.WriteLine("Writing result...");
      
              using (XmlTextWriter writer = new XmlTextWriter(filePath, Encoding.Default))
              {
                  writer.Formatting = Formatting.Indented;
                  xdoc.WriteTo(writer);
              }
          }
      
          /// <summary>
          /// Formats the string to pascal case, additionally checking for a period
          /// in the string (in which case it skips past the period, which indicates 
          /// the use of namespace in a string.
          /// </summary>
          /// <param name="str"></param>
          /// <param name="replaceUnderscores"></param>
          /// <returns></returns>
          private static string FormatString(string str, bool replaceUnderscores = true)
          {
              char[] chars = str.ToCharArray();
      
              var sb = new StringBuilder();
      
              bool previousCharWasUpper = false;
              bool lastOperationWasToLower = false;
      
              int startPos = 0;
      
              if (str.Contains("."))
              {
                  if (str.IndexOf(".") < (str.Length - 1))
                  {
                      startPos = str.IndexOf(".") + 1;
                  }
      
                  sb.Append(str.Substring(0, startPos));
              }
      
              for (int i = startPos; i < chars.Length; i++)
              {
                  char character = chars[i];
      
                  if (Char.IsLetter(character))
                  {
                      if (Char.IsLower(character))
                      {
                          bool toUpper = false;
      
                          if (i > 0)
                          {
                              // Look at the previous char to see if not a letter
      
                              if (!Char.IsLetter(chars[i - 1]))
                              {
                                  toUpper = true;
                              }
                          }
      
                          if (i == 0 || toUpper)
                          {
                              character = Char.ToUpper(character);
      
                              lastOperationWasToLower = false;
                          }
                      }
                      else // IsUpper = true
                      {
                          if (previousCharWasUpper || lastOperationWasToLower)
                          {
                              character = Char.ToLower(character);
      
                              lastOperationWasToLower = true;
                          }
                      }
      
                      previousCharWasUpper = Char.IsUpper(character);
      
                      sb.Append(character);
                  }
                  else
                  {
                      if (Char.IsDigit(character))
                      {
                          sb.Append(character);
      
                          previousCharWasUpper = false;
                          lastOperationWasToLower = false;
                      }
                      else if(!replaceUnderscores)
                      {
                          if(character == '_')
                          {
                              sb.Append(character);
                          }
                      }
                  }
              }
      
              return sb.ToString();
      
          }
      
          private static void StopWithMessage(string str)
          {
              Console.WriteLine(str);
      
              Console.ReadLine();
      
              throw new InvalidOperationException("Cannot continue.");
          }
      }
      }
      

    Edit by Chris

    Adapting to Visual Studio 2013 & EF6

    The code namespaces need a little tweak in order to make it work with EF6:

        const string CSDLNamespace = "http://schemas.microsoft.com/ado/2009/11/edm";
        const string MSLNamespace = "http://schemas.microsoft.com/ado/2009/11/mapping/cs";
        const string DiagramNamespace = "http://schemas.microsoft.com/ado/2009/11/edmx";
    
        const string CSNameSpace = "http://schemas.microsoft.com/ado/2009/11/mapping/cs";
    

    plus you need to take care of designerDiagram(in my case, it wasn't found, so just replaced First() with FirstOrDefault() and added simple null check).

    0 讨论(0)
  • some_class > SomeClass
    didn't work for me, instead I got:
    some_class > Someclass

    To fix it I moved
    previousCharWasUpper = false;
    a few lines up. It's near the end of the old code block.

            else
            {
                if (Char.IsDigit(character))
                {
                    sb.Append(character);
    
                    previousCharWasUpper = false;
                    lastOperationWasToLower = false;
                }
                else if(!replaceUnderscores)
                {
                    if(character == '_')
                    {
                        sb.Append(character);
                    }
                }
            }
    

    Changed to:

            else
            {
                previousCharWasUpper = false;
    
                if (Char.IsDigit(character))
                {
                    sb.Append(character);
    
                    lastOperationWasToLower = false;
                }
                else if(!replaceUnderscores)
                {
                    if(character == '_')
                    {
                        sb.Append(character);
                    }
                }
            }
    
    0 讨论(0)
  • 2021-01-16 21:27

    Update based on Chris' Edit To Original Answer

    This is the full C# .edmx modification code for use in an Entity Framework 6 context (original answer was for EF4).

    (Additional answer as opposed to edit due to character limit per answer)

    Thank you Chris for your input. I have recently revisited this as a project using this tool has been upgraded to EF6. The full code for use with EF6 is copied below.

    Note that this program code now operates on two files - the .edmx and the .edmx.diagram file. Visual Studio 2013 splits the diagram out into a separate file, and this needs editing otherwise the table / entity representations will not show up on the .edmx designer surface. The file path for the designer file is accepted as the second argument.

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace EdmxStringFormatter
    {
        public class Program
        {
            static void Main(string[] args)
            {
                if (args.Length < 1) return;
    
                string filePath = args[0];
                string designerFilePath = null;
    
                string entityName = null;
    
                // Optionally do not replace underscores which 
                // helps with naming collisions with siimilarly named
                // columns on some database tables.
    
                bool replaceUnderscores = true;
    
                // Allow for the replacement of the object context class name, which is useful
                // where multiple databases have edmx files.
    
                bool doEntityNameReplace = false;
    
                if (args.Length > 1)
                {
                    designerFilePath = args[1];
                }
    
                if (args.Length > 2)
                {
                    entityName = args[2];
                    doEntityNameReplace = true;
                }
    
                if (args.Length > 3)
                {
                    replaceUnderscores = args[3] != "0";
                }
    
                if (!File.Exists(filePath))
                {
                    StopWithMessage("Could not find specified file.");
                    return;
                }
                if (Path.GetExtension(filePath) != ".edmx")
                {
                    StopWithMessage("This works only on EDMX files.");
                    return;
                }
    
                TransformEdmx(filePath, replaceUnderscores, doEntityNameReplace, entityName);
                TransformEdmxDiagram(designerFilePath, replaceUnderscores);
            }
    
            private static void TransformEdmx(string filePath, bool replaceUnderscores, bool doEntityNameReplace, string entityName)
            {
                // Processing:
    
                Console.WriteLine("Creating backup: " + Path.ChangeExtension(filePath, ".bak"));
                File.Copy(filePath, Path.ChangeExtension(filePath, ".bak"), true);
    
                Console.WriteLine("Reading target document...");
    
                XDocument xdoc = XDocument.Load(filePath);
    
                //const string CSDLNamespace = "http://schemas.microsoft.com/ado/2008/09/edm";
                //const string MSLNamespace = "http://schemas.microsoft.com/ado/2008/09/mapping/cs";
                //const string DiagramNamespace = "http://schemas.microsoft.com/ado/2008/10/edmx";
    
                //const string CSNameSpace = "http://schemas.microsoft.com/ado/2008/09/mapping/cs";
    
                const string CSDLNamespace = "http://schemas.microsoft.com/ado/2009/11/edm";
                const string MSLNamespace = "http://schemas.microsoft.com/ado/2009/11/mapping/cs";
                const string DiagramNamespace = "http://schemas.microsoft.com/ado/2009/11/edmx";
    
                const string CSNameSpace = "http://schemas.microsoft.com/ado/2009/11/mapping/cs";
    
                XElement csdl = xdoc.Descendants(XName.Get("Schema", CSDLNamespace)).First();
                XElement msl = xdoc.Descendants(XName.Get("Mapping", MSLNamespace)).First();
    
                //modifications for renaming everything, not just table names:
    
                #region CSDL2
    
                Console.WriteLine("Modifying CSDL...");
                Console.WriteLine(" - modifying entity sets...");
    
                foreach (
                    var entitySet in
                        csdl.Element(XName.Get("EntityContainer", CSDLNamespace)).Elements(XName.Get("EntitySet", CSDLNamespace)))
                {
                    entitySet.Attribute("Name").Value = FormatString(entitySet.Attribute("Name").Value, replaceUnderscores);
                    entitySet.Attribute("EntityType").Value = FormatString(entitySet.Attribute("EntityType").Value,
                        replaceUnderscores);
                }
    
                Console.WriteLine(" - modifying association sets...");
                foreach (
                    var associationSet in
                        csdl.Element(XName.Get("EntityContainer", CSDLNamespace))
                            .Elements(XName.Get("AssociationSet", CSDLNamespace)))
                {
                    foreach (var end in associationSet.Elements(XName.Get("End", CSDLNamespace)))
                    {
                        end.Attribute("EntitySet").Value = FormatString(end.Attribute("EntitySet").Value, replaceUnderscores);
                    }
                }
    
                Console.WriteLine(" - modifying entity types...");
                foreach (var entityType in csdl.Elements(XName.Get("EntityType", CSDLNamespace)))
                {
                    entityType.Attribute("Name").Value = FormatString(entityType.Attribute("Name").Value, replaceUnderscores);
    
                    foreach (var key in entityType.Elements(XName.Get("Key", CSDLNamespace)))
                    {
                        foreach (var propertyRef in key.Elements(XName.Get("PropertyRef", CSDLNamespace)))
                        {
                            propertyRef.Attribute("Name").Value = FormatString(propertyRef.Attribute("Name").Value,
                                replaceUnderscores);
                        }
                    }
    
                    foreach (var property in entityType.Elements(XName.Get("Property", CSDLNamespace)))
                    {
                        property.Attribute("Name").Value = FormatString(property.Attribute("Name").Value, replaceUnderscores);
                    }
    
                    foreach (var navigationProperty in entityType.Elements(XName.Get("NavigationProperty", CSDLNamespace)))
                    {
                        navigationProperty.Attribute("Name").Value = FormatString(navigationProperty.Attribute("Name").Value,
                            replaceUnderscores);
                    }
                }
    
                Console.WriteLine(" - modifying associations...");
                foreach (var association in csdl.Elements(XName.Get("Association", CSDLNamespace)))
                {
                    foreach (var end in association.Elements(XName.Get("End", CSDLNamespace)))
                    {
                        end.Attribute("Type").Value = FormatString(end.Attribute("Type").Value, replaceUnderscores);
                    }
                    foreach (var propref in association.Descendants(XName.Get("PropertyRef", CSDLNamespace)))
                    {
                        //propertyrefs are contained in constraints
                        propref.Attribute("Name").Value = FormatString(propref.Attribute("Name").Value, replaceUnderscores);
                    }
                }
    
                #endregion
    
                #region MSL2
    
                Console.WriteLine("Modifying MSL...");
                Console.WriteLine(" - modifying entity set mappings...");
    
                foreach (
                    var entitySetMapping in
                        msl.Element(XName.Get("EntityContainerMapping", MSLNamespace))
                            .Elements(XName.Get("EntitySetMapping", MSLNamespace)))
                {
                    entitySetMapping.Attribute("Name").Value = FormatString(entitySetMapping.Attribute("Name").Value,
                        replaceUnderscores);
    
                    foreach (var entityTypeMapping in entitySetMapping.Elements(XName.Get("EntityTypeMapping", MSLNamespace)))
                    {
                        entityTypeMapping.Attribute("TypeName").Value = FormatString(entityTypeMapping.Attribute("TypeName").Value,
                            replaceUnderscores);
                        foreach
                            (var scalarProperty in
                                (entityTypeMapping.Element(XName.Get("MappingFragment", MSLNamespace))).Elements(
                                    XName.Get("ScalarProperty", MSLNamespace))
                            )
                        {
                            scalarProperty.Attribute("Name").Value = FormatString(scalarProperty.Attribute("Name").Value,
                                replaceUnderscores);
                        }
                    }
                }
    
                Console.WriteLine(" - modifying association set mappings...");
    
                foreach (
                    var associationSetMapping in
                        msl.Element(XName.Get("EntityContainerMapping", MSLNamespace))
                            .Elements(XName.Get("AssociationSetMapping", MSLNamespace)))
                {
                    foreach (var endProperty in associationSetMapping.Elements(XName.Get("EndProperty", MSLNamespace)))
                    {
                        foreach (var scalarProperty in endProperty.Elements(XName.Get("ScalarProperty", MSLNamespace)))
                        {
                            scalarProperty.Attribute("Name").Value = FormatString(scalarProperty.Attribute("Name").Value,
                                replaceUnderscores);
                        }
                    }
                }
    
                #endregion
    
                // Optionally replace the entity name in case the default of "Entity" is not
                // sufficient for your needs.
    
                if (doEntityNameReplace)
                {
                    Console.WriteLine("Modifying entity name refs...");
    
                    // CSDL
                    xdoc.Descendants(XName.Get("EntityContainer", CSDLNamespace)).First().Attribute("Name").Value = entityName;
    
                    // Diagram 
                    var diagramDescendants = xdoc.Descendants(XName.Get("Diagram", DiagramNamespace)).FirstOrDefault();
    
                    if (diagramDescendants != null)
                    {
                        diagramDescendants.Attribute("Name").Value = entityName;
                    }
    
                    // Diagram 
                    xdoc.Descendants(XName.Get("EntityContainerMapping", CSNameSpace)).First().Attribute("CdmEntityContainer").Value
                        = entityName;
                }
    
                Console.WriteLine("Writing result...");
    
                using (XmlTextWriter writer = new XmlTextWriter(filePath, Encoding.Default))
                {
                    writer.Formatting = Formatting.Indented;
                    xdoc.WriteTo(writer);
                }
            }
    
            private static void TransformEdmxDiagram(string filePath, bool replaceUnderscores)
            {
                // Processing:
    
                Console.WriteLine("Creating backup: " + Path.ChangeExtension(filePath, ".bak"));
                File.Copy(filePath, Path.ChangeExtension(filePath, ".bak"), true);
    
                Console.WriteLine("Reading target document...");
    
                XDocument xdoc = XDocument.Load(filePath);
    
                const string DiagramNamespace = "http://schemas.microsoft.com/ado/2009/11/edmx";
    
                XElement designerDiagram = xdoc.Descendants(XName.Get("Diagram", DiagramNamespace)).FirstOrDefault();
    
    
                #region Designer
    
                Console.WriteLine("Modifying designer content...");
    
                if (designerDiagram != null)
                {
                    foreach (var item in designerDiagram.Elements(XName.Get("EntityTypeShape", DiagramNamespace)))
                    {
                        item.Attribute("EntityType").Value = FormatString(item.Attribute("EntityType").Value, replaceUnderscores);
                    }
                }
    
                #endregion
    
                Console.WriteLine("Writing result...");
    
                using (XmlTextWriter writer = new XmlTextWriter(filePath, Encoding.Default))
                {
                    writer.Formatting = Formatting.Indented;
                    xdoc.WriteTo(writer);
                }
            }
    
            /// <summary>
            /// Formats the string to pascal case, additionally checking for a period
            /// in the string (in which case it skips past the period, which indicates 
            /// the use of namespace in a string.
            /// </summary>
            /// <param name="str"></param>
            /// <param name="replaceUnderscores"></param>
            /// <returns></returns>
            private static string FormatString(string str, bool replaceUnderscores = true)
            {
                char[] chars = str.ToCharArray();
    
                var sb = new StringBuilder();
    
                bool previousCharWasUpper = false;
                bool lastOperationWasToLower = false;
    
                int startPos = 0;
    
                if (str.Contains("."))
                {
                    if (str.IndexOf(".") < (str.Length - 1))
                    {
                        startPos = str.IndexOf(".") + 1;
                    }
    
                    sb.Append(str.Substring(0, startPos));
                }
    
                for (int i = startPos; i < chars.Length; i++)
                {
                    char character = chars[i];
    
                    if (Char.IsLetter(character))
                    {
                        if (Char.IsLower(character))
                        {
                            bool toUpper = false;
    
                            if (i > 0)
                            {
                                // Look at the previous char to see if not a letter
    
                                if (!Char.IsLetter(chars[i - 1]))
                                {
                                    toUpper = true;
                                }
                            }
    
                            if (i == 0 || toUpper)
                            {
                                character = Char.ToUpper(character);
    
                                lastOperationWasToLower = false;
                            }
                        }
                        else // IsUpper = true
                        {
                            if (previousCharWasUpper || lastOperationWasToLower)
                            {
                                character = Char.ToLower(character);
    
                                lastOperationWasToLower = true;
                            }
                        }
    
                        previousCharWasUpper = Char.IsUpper(character);
    
                        sb.Append(character);
                    }
                    else
                    {
                        if (Char.IsDigit(character))
                        {
                            sb.Append(character);
    
                            previousCharWasUpper = false;
                            lastOperationWasToLower = false;
                        }
                        else if (!replaceUnderscores)
                        {
                            if (character == '_')
                            {
                                sb.Append(character);
                            }
                        }
                    }
                }
    
                return sb.ToString();
    
            }
    
            private static void StopWithMessage(string str)
            {
                Console.WriteLine(str);
    
                Console.ReadLine();
    
                throw new InvalidOperationException("Cannot continue.");
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题