开发者

Replacing hardcoded strings with constants in C#

I am trying to take all the hardcoded strings in a .cs file and load it from a constant file.

For instance

string capital="Washington";

should be loaded as

string capital=Constants.capital;

and that will be added in Constants.cs

public final const capital="Washington";

I need a java/C# snippet to do this.I can't use any third party tools.Any help on this?

EDIT:

After readin开发者_运维百科g the comments and answers I get a feeling I am not clear.I just want a way to replace all hard coded constants which will be having "" and rip that off and replace it with the Constants. and add that property in Constants.cs.This can be a simple text processing as well.


A few hints that should get you started:

Assume that your string processor function is called ProcessStrings.

1) Include Constants.cs into the same project as the ProcessStrings function, so it gets compiled in with the refactoring code.

2) Reflect over your Constants class to build a Dictionary of language strings to constant names, something like:

Dictionary<String, String> constantList = new Dictionary<String, String>();
FieldInfo[] fields = typeof(Constants).GetFields(BindingFlags.Static | BindingFlags.Public);
String constantValue;

foreach (FieldInfo field in fields)
{
    if (field.FieldType == typeof(String))
    {                    
        constantValue = (string)field.GetValue(null);             
        constantList.Add(constantValue, field.Name);
    }
}

3) constantList should now contain the full list of Constant names, indexed by the string they represent.

4) Grab all the lines from the file (using File.ReadAllLines).

5) Now iterate over the lines. Something like the following should allow you to ignore lines that you shouldn't be processing.

//check if the line is a comment or xml comment
if (Regex.IsMatch(lines[idx], @"^\s*//")) 
    continue;

//check if the entry is an attribute
if (Regex.IsMatch(lines[idx], @"^\s*\["))
    continue;

//check if the line is part of a block comment (assuming a * at the start of the line)
if (Regex.IsMatch(lines[idx], @"^\s*(/\*+|\*+)"))
    continue;

//check if the line has been marked as ignored 
//(this is something handy I use to mark a string to be ignored for any reason, just put //IgnoreString at the end of the line)
if (Regex.IsMatch(lines[idx], @"//\s*IgnoreString\s*$")) 
    continue;

6) Now, match any quoted strings on the line, then go through each match and check it for a few conditions. You can remove some of these conditions if needs be.

MatchCollection mC = Regex.Matches(lines[idx], "@?\"([^\"]+)\"");

foreach (Match m in mC)
{                           

    if (            
        // Detect format insertion markers that are on their own and ignore them, 
        !Regex.IsMatch(m.Value, @"""\s*\{\d(:\d+)?\}\s*""") &&
        //or check for strings of single character length that are not proper characters (-, /, etc)
        !Regex.IsMatch(m.Value, @"""\s*\\?[^\w]\s*""") &&
        //check for digit only strings, allowing for decimal places and an optional percentage or multiplier indicator
        !Regex.IsMatch(m.Value, @"""[\d.]+[%|x]?""") &&
        //check for array indexers
        !(m.Index <= lines[idx].Length && lines[idx][m.Index - 1] == '[' && lines[idx][m.Index + m.Length] == ']')  &&          
        )
    {
        String toCheck = m.Groups[1].Value;

        //look up the string we found in our list of constants
        if (constantList.ContainsKey(toCheck))
        {
            String replaceString;

            replaceString = "Constants." + constants[toCheck];              

            //replace the line in the file
            lines[idx] = lines[idx].Replace("\"" + m.Groups[1].Value + "\"", replaceString);
        }
        else
        {

            //See Point 8....

        }
    }

7) Now join the array of lines back up, and write it back to the file. That should get you most of the way.

8) To get it to generate constants for strings you don't already have an entry for, in the else block for looking up the string, generate a name for the constant from the string (I just removed all special characters and spaces from the string and limited it to 10 words). Then use that name and the original string (from the toCheck variable in point 6) to make a constant declaration and insert it into Constants.cs. Then when you run the function again, those new constants will be used.


I don't know if there is any such code available, but I am providing some guidelines on how it can be implemented.

  1. You can write a macro/standalone application (I think macro is a better option)
  2. Parse current document or all the files in the project/solution
  3. Write a regular expression for finding the strings (what about strings in XAML?). something like [string]([a-z A-Z0-9])["]([a-z A-Z0-9])["][;] -- this is not valid, I have just provide for discussion
  4. Extract the constant from code.
  5. Check if similar string is already there in your static class
  6. If not found, insert new entry in static class
  7. Replace string with the variable name
  8. Goto step 2


Is there a reason why you can't put these into a static class or just in a file in your application? You can put constants anywhere and as long as they are scoped properly you can access them from everywhere.


public const string capital = "Washington";

if const doesn't work in static class, then it would be

public static readonly string capital = "Washington";


if you really want to do it the way you describe, read the file with a streamreader, split by \r\n, check if the first thing is "string", and then do all your replacements on that string element... make sure that every time you change that string declaration, you add the nessesary lines to the other file.


You can create a class project for your constants, or if you have a helper class project, you can add a new class for you constants (Constants.cs).

public static class Constants
{
   public const string CAPITAL_Washington = "Washington";
}

You can now use this:

string capital = Constants.CAPITAL_Washington;

You might as well name your constants quite specific.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜