Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I went ahead and wrote a C# utility to parse such a class file. The "protected set" idea is valid to a point (thanks Hazzik), but it still needs a backing field. The below code produces the output I described above (except uses a "protected set"). Regards, -Dave</p> <pre class="lang-cs prettyprint-override"><code>using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace ConsoleApplication3 { // TODO: write recursive algorithm to loop through directories // TODO: handle generic collections as Fluent NHibernate treats those differently class Program { public static string ConvertInitialCapitalToUnderscoreAndLowerCase(string input) { var firstChar = input.Substring(0, 1); var restOfStmt = input.Substring(1); var newFirst = "_" + firstChar.ToLower(); var output = newFirst + restOfStmt; return output; } // this gets any tabs or spaces at the beginning of the line of code as a string, // so as to preserve the indentation (and/or add deeper levels of indentation) public static string GetCodeLineIndentation(string input) { var charArray = input.ToCharArray(); var sbPrefix = new StringBuilder(); foreach (var c in charArray) { // if it's a tab or a space, add it to the "prefix" if (c == 9 || c == ' ') { sbPrefix.Append(c); } else { // get out as soon as we hit the first ascii character (those with a value up to 127) break; } } return sbPrefix.ToString(); } static void Main(string[] args) { const string path = @"C:\pathToFile\Status.cs"; Console.WriteLine("Examining file: " + path); if (!File.Exists(path)) { Console.WriteLine("File does not exist: " + path); throw new FileNotFoundException(path); } // Read the file. var arrayOfLines = File.ReadAllLines(path); // Convert to List&lt;string&gt; var inputFileAsListOfStrings = new List&lt;string&gt;(arrayOfLines); // See if there are any virtual properties. var virtualProps = inputFileAsListOfStrings.Where(s =&gt; s.Contains("public virtual")).ToList(); // See if there are any "private set" strings. var privateSets = inputFileAsListOfStrings.Where(s =&gt; s.Contains("private set")).ToList(); if (virtualProps.Count &gt; 0) { Console.WriteLine("Found " + virtualProps.Count + " virtual properties in the class..."); } if (privateSets.Count &gt; 0) { Console.WriteLine("Found " + privateSets.Count + " private set statements in the class..."); } // Get a list of names of the virtual properties // (the 4th "word", i.e. index = 3, in the string, will be the property name, // e.g. "public virtual string SomePropertyName" var virtualPropNames = virtualProps.Select(vp =&gt; vp.Trim().Split(' ')).Select(words =&gt; words[3]).ToList(); if (virtualPropNames.Count() != virtualProps.Count()) { throw new Exception("Error: the list of virtual property names does not equal the number of virtual property statements!"); } // Find all instances of the virtual properties being initialized. // By examining the overall file for instances of the virtual property name followed by an equal sign, // we can identify those lines which are statements initializing the virtual property. var initializeStatements = (from vpName in virtualPropNames from stmt in inputFileAsListOfStrings let stmtNoSpaces = stmt.Trim().Replace(" ", "") where stmtNoSpaces.StartsWith(vpName + "=") select stmt).ToList(); if (initializeStatements.Count() &gt; 0) { Console.WriteLine("Found " + initializeStatements.Count + " initialize statements in the class..."); } // now process the input based on the found strings and write the output var outputFileAsListOfStrings = new List&lt;string&gt;(); foreach (var inputLineBeingProcessed in inputFileAsListOfStrings) { // is the input line one of the initialize statements identified previously? // if so, rewrite the line. // e.g. // old line: StatusText = statusText; // becomes: _statusText = statusText; var isInitStmt = false; foreach (var initStmt in initializeStatements) { if (inputLineBeingProcessed != initStmt) continue; // we've found our statement; it is an initialize statement; // now rewrite the format of the line as desired var prefix = GetCodeLineIndentation(inputLineBeingProcessed); var tabAndSpaceArray = new[] {' ', '\t'}; var inputLineWithoutPrefix = inputLineBeingProcessed.TrimStart(tabAndSpaceArray); var outputLine = prefix + ConvertInitialCapitalToUnderscoreAndLowerCase(inputLineWithoutPrefix); // write the line (preceded by its prefix) to the output file outputFileAsListOfStrings.Add(outputLine); Console.WriteLine("Rewrote INPUT: " + initStmt + " to OUTPUT: " + outputLine); isInitStmt = true; // we have now processed the input line; no need to loop through the initialize statements any further break; } // if we've already determined the current input line is an initialize statement, no need to proceed further; // go on to the next input line if (isInitStmt) continue; // is the input line one of the "public virtual SomeType SomePropertyName" statements identified previously? // if so, rewrite the single line as multiple lines of output. // the input will look like this: /* public virtual SomeType SomePropertyName { get; set; } */ // first, we'll need a private variable which corresponds to the original statement in terms of name and type. // what we'll do is, write the private field AFTER the public property, so as not to interfere with the XML // comments above the "public virtual" statement. // the output will be SIX LINES, as follows: /* public virtual SomeType SomePropertyName { get { return _somePropertyName; } protected set { _someProperty = value; } } private SomeType _somePropertyName; */ var isPublicVirtualStatement = false; foreach (var vp in virtualProps) { if (inputLineBeingProcessed != vp) continue; // the input line being processed is a "public virtual" statement; // convert it into the six line output format var thisOutputList = new List&lt;string&gt;(); // first separate any indentation "prefix" that may exist (i.e. tabs and/or spaces), // from the actual string of text representing the line of code var prefix = GetCodeLineIndentation(inputLineBeingProcessed); var tabAndSpaceArray = new[] { ' ', '\t' }; var inputLineWithoutPrefix = inputLineBeingProcessed.TrimStart(tabAndSpaceArray); var originalVpStmt = inputLineWithoutPrefix.Split(' '); // first output line (preceded by its original prefix) var firstOutputLine = prefix + originalVpStmt[0] + ' ' + originalVpStmt[1] + ' ' + originalVpStmt[2] + ' ' + originalVpStmt[3]; thisOutputList.Add(firstOutputLine); // second output line (indented to the same level as the original prefix) thisOutputList.Add(prefix + "{"); // get field name from property name var fieldName = ConvertInitialCapitalToUnderscoreAndLowerCase(originalVpStmt[3]); // third output line (indented with the prefix, plus one more tab) var thirdOutputLine = prefix + "\t" + "get { return " + fieldName + "; }"; thisOutputList.Add(thirdOutputLine); // fourth output line (indented with the prefix, plus one more tab) var fourthOutputLine = prefix + "\t" + "protected set { " + fieldName + " = value; }"; thisOutputList.Add(fourthOutputLine); // fifth output line (indented to the same level as the first curly bracket) thisOutputList.Add(prefix + "}"); // sixth output line (the "index 2" value of the original statement will be the string representing the .Net type) // (indentation is the same as the "public virtual" statement above) var sixthOutputLine = prefix + "private" + ' ' + originalVpStmt[2] + ' ' + fieldName + ";"; thisOutputList.Add(sixthOutputLine); // now write the six new lines to the master output list outputFileAsListOfStrings.AddRange(thisOutputList); isPublicVirtualStatement = true; Console.WriteLine("Rewrote INPUT: " + inputLineBeingProcessed + " to OUTPUT: &lt;multi-line block&gt;"); break; } // if we've already determined the current input line is a "public virtual" statement, no need to proceed further; // go on to the next input line if (isPublicVirtualStatement) continue; // if we've gotten this far, the input statement is neither an "initialize" statement, nor a "public virtual" statement; // So just write the output. Don't bother logging this as most lines will not be ones we'll process. outputFileAsListOfStrings.Add(inputLineBeingProcessed); } // write the output file var newPath = path.Replace(".cs", "-NEW.cs"); File.WriteAllLines(newPath, outputFileAsListOfStrings); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload