问题
I have a class that reads in text from a spreadsheet using EPPlus. It works and it does exactly what I want it to do but I feel the way I did it is bad practice but for the life of me I cant figure out an alternative that is less hard coded and uses less if statements. the class contains constants such as
private static string configUserName;
private static string configPassword;
private static string configUrl;
private static string configDatabase;
//etc
There are about 40 of these. The class loops through a spread sheet reading all the values checking which value it is like:
int i = 1;
object isRow = currentWorksheet.Cells[i, 1].Value;
while (isRow != null)
{
if (isRow.ToString().Trim().Equals("change_bank_details_policy"))
{
if (currentWorksheet.Cells[i, 2].Value != null)
{
change_bank_details_policy =c currentWorksheet.Cells[i,2].Value.ToString().Trim();
}
}
else if //etc 40 more if statements
Then because the values are private there are 40 methods such as
public static string GetConfigUserName()
{
return configUserName;
}
There must be a better way to do this? the spreadsheet looks like
change_bank_details_policy,11459676
change_DD_date_policy,11441975
[40 more rows....]
回答1:
Can you make a Dictionary (with Key String
, and value Int
) that maps together the string and the value?
Read the Excel sheet one row at a time, to build your Dictionary.
Then use the dictionary to set the proper variables.
Then afterwards your dictionary looks like:
KEY VALUE
============================|========
change_bank_details_policy |11459676
change_DD_date_policy |11441975
and after the Dictionary is built, you can simply do:
change_bank_details_policy = my_dictionary["change_bank_details_policy"];
I think the outline would look like:
Dictionary<String, UInt32> myDict = new Dictionary<String, UInt32>();
object isRow = currentWorksheet.Cells[i, 1].Value;
while (isRow != null)
{
myDict.Add(isRow.ToString().Trim(), currentWorksheet.Cells[i,2].Value);
// Go get the next Row.... details are up to you.
}
change_bank_details_policy = myDict["change_bank_details_policy"]; // Look up this key in the dictionary to get this integer....
change_DD_date_policy = myDict["change_DD_date_policy"];
// [... repeat 40 more times ... but no If statements ]
回答2:
The root of the problem is the fact that you have ~40 variables, this is a definite code smell. You should consider using a Dictionary, for example to store them - rather than extensive usage of variables.
A Dictionary
is mapping from a 'key' to a 'value'. In your case, it will map from a string to a string (if you actually need a string for them).
回答3:
Switch statements were mentioned already, but one nifty feature in C# is that you can set direct access to a variable as read-only, so to answer your second question your variables could have the following syntax:
private static string configUserName
{
public get;
private set;
}
Which would allow your class members to access the variable directly, but will cause a compiler error if a user tries to write to it directly (but not if they try to read it), so for example:
instance.configUserName = "Bob";
Will work in class-member code, but will not compile in user code, while:
String bob = instance.configUserName;
Will compile in both places.
回答4:
The following code does not override unread values. If a row is not present in the source file, previous values are not lost. I think it is a bit more bulletproof on source file content.
var dict = new Dictionary<string, Action<long>>();
dict.Add("change_bank_details_policy", v => change_bank_details_policy = v);
// 40 of these, no choice
int i = 1;
object isRow = currentWorksheet.Cells[i, 1].Value;
while (isRow != null)
{
string rowTitle = isRow.ToString().Trim();
if (dict.ContainsKey(rowTitle))
{
// Or parse it or whatever you have to do to handle the cell value type
long rowValue = currentWorksheet.Cells[i,2].Value;
dict[rowtitle](rowValue);
}
isRow = currentWorksheet.Cells[++i, 1].Value;
}
来源:https://stackoverflow.com/questions/22640339/too-many-if-statements