문제

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....]
도움이 되었습니까?

해결책

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 ]

다른 팁

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).

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.

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;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top