2

My question is sort of like the one found here: How do I name variables dynamically in C#? However its a bit different so I'm wondering if its possible.

I'm trying to read in a bunch of strings from a .settings file. I have them all named Time1, Time2,Time3 etc... I want the User to be able to add more Times to the file so there could be Time100 or more. I have a Size in the settings file that will keep track of the amount of Time Variables. I want to write something that will read in all of the Time strings. I think it would be silly to pre-fill the .settings file with 100 Time Variables so I know they are there and then manually read in each one.
So I'm wondering if there is a way where I can read in Timei or Time+i where I is an integer that I can put in a loop that will find them all. (note that the data is string not time, its just going to be converted to days of the week) Such as: (Days is from ApplicationSettingsBase [aka file add new Settings1.settings]

    public static int AvDaysIndex = Days.Default.Size; //This holds the number of items in Days
    public static DayOfWeek[] AvailableDays = new DayOfWeek[AvDaysIndex]; //This is where I wants to read in all the variables Aka Time1 Time2 Times3 


    public ReadInDays() //Reads in from the .settings File
    {
        if(AvDaysIndex>0) // Makes sure there is something in Days to read
        {
              int I=0;
              //I can Manually do the following
               AvailableDays[I++] = Days.Default.Time1;
               AvailableDays[I++] = Days.Default.Time2;
               AvailableDays[I++] = Days.Default.Time3; //etc...


             //Is there a way to do something like this
            for (int i = 0; i < AvDaysIndex; i++) //reads in each time
            { 
                AvailableDays[i] = Days.Default.Time +i;//where I would be added to the variable name to find it?

               //Or something like
               AvailableDays[i] = Days.Default.Time(I.tostring())
            }
        }
    }

Hopefully all that at least makes it clear what I'm trying to do.

Edit - I'm starting to think my issue is actually with the .settings file. and that if I just read values in from another file type where the values don't have names I can easily read them in even though there is a variable number of elements in the file.

Solution -

            for (int i = 0; i < Index; i++)
            {
                AvailableDays[i] = getFromFile(_Days.Default.Properties["Time" + (i+1).ToString()].DefaultValue.ToString());
                AvailableTimes[i] = Convert.ToDateTime(_Times.Default.Properties["Time" + (i + 1).ToString()].DefaultValue);  
            }  

It was all in figuring out how to read in from the .settings file and instead of reading it in directly aka Days.Default.Time1; I had to to do a generic lookup from Days.Default.Properties and then I could create a dynamic name and find it. You guys probably were trying to tell me how to do this, I just didn't understand.

Thanks again to all those that helped.

Community
  • 1
  • 1
Krell
  • 55
  • 1
  • 6
  • 2
    why don't use a dictionary instead? – Felice Pollano Jun 11 '13 at 05:14
  • I don't know how many .Time# s there will be. There may be 5 there may be 400. So I was trying to find something that was dynamic. I thought if I use a library that I have to precode all the Times up to a certain amount then limit the user to that many times. (is this a correct assumption) – Krell Jun 11 '13 at 16:47

4 Answers4

7

I would use a hashtable/dictionary to store the Days.Default.TimeX variations

hashtable["Time1"]...hashtable["TimeN"]
TGH
  • 38,769
  • 12
  • 102
  • 135
  • With a hashtable don't I have to precode all the Times a head of time? Aka up to 400 if there might be 400 times. even if there are actually only 4? I don't know how many .Time# s there will be. There may be 4 there may be 400. I wanted to make it so that users could have as little as 1 time or as many as they wanted. – Krell Jun 11 '13 at 16:50
2

Another option could be to use Reflection. And getting the values from the enum on the fly.

See the link: How to Get Enum Values with Reflection in C#

However, using a Dictionary<string, DayOfWeek> will give you better performance and more readable code.

Ali
  • 1,409
  • 13
  • 23
  • I'm not quite sure how reflection will enable me the variables from the file without hard coding the names. I get how to use reflection or a dictionary AFTER I have read them in, that's easy. My question is more so, is there a way to read in things dynamically I guess. (thanks) – Krell Jun 11 '13 at 17:07
2

As already mentioned a hashtable or a dictionary would probably serve you best. If you go the dictionary route you can create a string/int indexer on the class and you would be able to alter your code slightly:

http://msdn.microsoft.com/en-us/library/2549tw02%28v=vs.80%29.aspx - Example of creating indexer on a class:

Example Indexer Class:

public class Default
{
    private Dictionary<int, DayOfWeek> _values = new Dictionary<int,DayOfWeek>();

    public DayOfWeek this[int index]
    {
        get
        {
            if (_values.ContainsKey(index))
                return _values[index];
            else
                return null;
        }
        set
        {
            _values[index] = value;
        }
    }
}

Original:

AvailableDays[i] = Days.Default.Time(I.tostring())

Would become:

AvailableDays[i] = Days.Default.Time[I];

Reflection is always an option too and i have an example below that is in a Windows Console Application:

public class Default
{
    public int Time1 { get; set; }
    public int Time2 { get; set; }
    public int Time3 { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        Default d = new Default();
        Type t = d.GetType();

        foreach (var info in t.GetProperties())
        {
            //SET VALUE
            info.SetValue(d, 1);
        }

        foreach (var info in t.GetProperties())
        {
            //GET VALUE
            Console.WriteLine("Property: {0}", info.Name);
            Console.WriteLine("Value: {0}", info.GetValue(d));
        }

        //OR JUST ONE PROPERTY
        Console.WriteLine("Time1 Property Value: {0}", t.GetProperty("Time1").GetValue(d));

        Console.ReadLine();//PAUSE THE CONSOLE AFTER PROCESSING
    }
}

In your example using reflection:

Days.Default.GetType().GetProperty("Time" + I.ToString()).GetValue(Days.Default) as DayOfWeek;
  • Thanks for the response, It actually helped me figure out some stuff I was struggling with, however it still doesn't answer the question I'm trying to ask. (I'm probably just asking it improperly, I'm very new to c#) It seems that this will let me read in predefined things just like I want, I'm still not sure how you would use this with the .settings file. (Maybe I should just make my own file and output stuff there and then read it in one at a time, then the names don't matter) Thanks again – Krell Jun 11 '13 at 17:35
  • Thanks! This helped the most. I figured it out! for (int i = 0; i < Index; i++) { AvailableDays[i] = getFromFile(_Days.Default.Properties["Time" + (i+1).ToString()].DefaultValue.ToString()); AvailableTimes[i] = Convert.ToDateTime(_Times.Default.Properties["Time" + (i + 1).ToString()].DefaultValue); } //getfromfile is just a helper I wrote to convert the sting to a truefalse struct – Krell Jun 11 '13 at 18:34
0

I think you could better resolve your problem by implementing your configuration using a ConfigurationElementCollection. Then the 'names' of the configuration elements are irrelevant. You enumerate a collection of values and use those directly.

See here for an example; How to implement a ConfigurationSection with a ConfigurationElementCollection.

Community
  • 1
  • 1
RJ Lohan
  • 6,497
  • 3
  • 34
  • 54
  • I didn't even know about ConfigurationElementCollection. I'm going to go read up on it. Thanks for the idea. Be back when I know more. – Krell Jun 11 '13 at 17:36