-1

I have config values as shown below

add key="Screen1" value ="Admin"
add key="Screen2" value ="Log"

In future new screens will get added. In C#, I need to create an array of string with these screen names. How can we do this (keeping in mind that the code need to work even if we add new screens)?

Note 1: I am looking for an approach that does not use custom configuration.

Note 2: I will have maximum of 10 config items with the name starting as "Screen". But I will have 10,000 other config items.

REFERENCE

  1. Better code/ Pattern for checking existence of value
  2. Generic method for reading config sections
  3. Generating numbers list in C#
  4. Detecting sequence of at least 3 sequential numbers from a given list
  5. Does LINQ cache computed values?
  6. Is there an easy method to combine two relative paths in C#?
Community
  • 1
  • 1
LCJ
  • 22,196
  • 67
  • 260
  • 418
  • I might be missing something, but I don't see the connection between the issue and custom authentication – Alex Aug 02 '12 at 14:57
  • 1
    Ok now it all makes more sense. Oded's answer is very right. – Alex Aug 02 '12 at 15:04
  • "I am looking for an approach that does not use custom configuration." - No other solution exists. – Security Hound Aug 02 '12 at 15:06
  • Don't understand why you don't want a custom configuration. Are you asking how to read those values? Rather than an array read them into a DictionaryList. – paparazzo Aug 02 '12 at 15:07
  • 1
    @Ramhound: Bull poo. Of course there is another way. Just enumerate all settings keys and take those starting with "Screen". – Fyodor Soikin Aug 02 '12 at 15:34

3 Answers3

3
ConfigurationManager.AppSettings.AllKeys
    .Where( key => key.StartsWith( "Screen" ) )
    .Select( key => ConfigurationManager.AppSettings[key] )

If you have a lot of settings (say, 10K, like you specified in the comments), you may benefit from the fact that the AppSettings collection is optimized for lookup by key. For this, you'll have to repeatedly try "Screen1", "Screen2", "Screen3", etc., and stop when no value is found:

Enumerable.Range( 1, int.MaxValue )
    .Select( i => ConfigurationManager.AppSettings[ "Screen" + i ] )
    .TakeWhile( value => value != null )

This approach, however, is exactly the kind of "premature optimization" that Mr. Knuth warned us about. The config file simply shouldn't contain that many settings, period.

Another disadvantage: keep in mind that this approach assumes that there are no gaps in the numbering of "Screen*" settings. That is, if you have "Screen1", "Screen2", and "Screen4", it will not pickup the last one. If you're planning on having a lot of these settings, it will become very inconvenient to "shift" all the numbers every time you add or remove a setting.

Fyodor Soikin
  • 78,590
  • 9
  • 125
  • 172
  • Thanks. This is definitely the answer for what I asked. But,now, I am scared about performance issues. – LCJ Aug 02 '12 at 15:33
  • @Lijo: don't see any issues with performance, unless you have thousands of configuration settings. But, like I said before: the best way is definitely to use a dedicated data structure for access control. – Fyodor Soikin Aug 02 '12 at 15:36
  • I will have maximum of 10 config items with the name starting as "Screen". But I will have 10,000 other config items. Will LINQ do it smartly by looking only for the items with "Screen" or will it scan through all 10000 items? – LCJ Aug 02 '12 at 15:40
  • @Lijo Leaving beside the fact that 10000 settings seems like much, just measure it mate. Add 20000 settings and see how it goes. If it is slow then cache it. – tymtam Aug 02 '12 at 15:47
  • @Lijo: 10K configuration settings is A LOT, man. You should definitely, absolutely, totally, redesign your application to use something else for data storage. Config file is not for that. To answer your question: of course this code will scan the whole thing. In order to call the `StartsWith` method on every item, it must consider every item. That's sort of how the universe works. – Fyodor Soikin Aug 02 '12 at 15:52
  • @Lijo: Don't bother with imaginative scenarios that are not going to actually happen. Gather requirements, do measurements, then decide. Oh, and by the way, take a look at this quote from one smart fella: http://shreevatsa.wordpress.com/2008/05/16/premature-optimization-is-the-root-of-all-evil/ – Fyodor Soikin Aug 02 '12 at 15:58
  • @Lijo: Define "smartly". Like I said repeatedly before, keeping access control in web.config is not a smart idea, and neither is having 10K settings. Doesn't that matter to your reviewers? – Fyodor Soikin Aug 02 '12 at 16:05
  • 1
    @Lijo: To answer your question, though. Yes, there is a way to not scan the whole thing... Sort of. When you access a settings value by name, i.e. `ConfigurationManager.AppSettings["MySetting"]`, then it doesn't scan the whole thing, but uses a data structure optimized for look-up by key (specifically, a hash table). You can use this by repeatedly trying "Screen1", "Screen2", "Screen3", and so on. Each of those will be of complexity O(1), which will give you the total of O(K) where K is the actual number of "Screen*" settings, not the total number of settings. See my edit. – Fyodor Soikin Aug 02 '12 at 16:11
  • @Lijo: LINQ 2 SQL does that because it translates your C# code into SQL and ships it off to the DB server for execution. Then the DB server only returns whatever is specified in your code. In this case, however, you're not sending your query anywhere, but simply operate on objects in your memory. But more to the point, an example is not a definition. If "smartly" is a vague intuitive category that only exists in the minds of your reviewers, then you don't have a chance whatever you do. – Fyodor Soikin Aug 02 '12 at 16:16
  • 1
    @Lijo: keep in mind that my updated answer assumes that there are no gaps in the numbering of "Screen*" settings. That is, if you have "Screen1", "Screen2", and "Screen4", it will not pickup the last one. If you're planning on having a lot of these settings, it will become very inconvenient to "shift" all the numbers every time you add or remove a setting. – Fyodor Soikin Aug 02 '12 at 16:18
  • 2
    @Lijo: Ok, man, I did update the answer, but you know what, at this point I'm starting to feel like I'm straight up being used. You don't show any effort on your part, but expect the community to solve your problems for free. This is unfair at the least. I am not answering any more requests or comments. – Fyodor Soikin Aug 02 '12 at 16:26
  • I was only trying to help the community. If people read the answer without this specific point, they may run into bugs. I just wanted to help them. – LCJ Aug 02 '12 at 16:35
  • +1 Way more patience than me. I would have stopped at "its imaginative scenario". That is just misuse of SO. Gave no reason for not using Custom Configuration. – paparazzo Aug 02 '12 at 20:45
2

Create your own configuration section as described in the answer to this question.

By doing so, you have full control over the content in the config file and how it gets exposed to the application.

Also see How to: Create Custom Configuration Sections Using ConfigurationSection on MSDN for a step by step tutorial.

Community
  • 1
  • 1
Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • Thanks. I think, this will be the best solution. But I am looking for an approach that does not use custom configuration. – LCJ Aug 02 '12 at 14:55
  • @Lijo - The link to the MSDN article doesn't have any authentication requirements. – Oded Aug 02 '12 at 14:57
0

I'm not entirely sure if understand the issue but you could enumerate the settings and pick all that start with "Screen".

Have a look at Enumerating Settings in .NET Applications.

tymtam
  • 31,798
  • 8
  • 86
  • 126
  • I think, this will cause performance issues. I will have maximum of 10 config items with the name starting as "Screen". But I will have 10,000 other config items. – LCJ Aug 02 '12 at 15:46
  • @Lijo - don't think - just try it :) Access to settings is cached normally, but I don't know this behaves with 10000 settings. – tymtam Aug 02 '12 at 15:49