Is it good that reading config values rather than using magic numbers? - c#

I have an idea that reading values from config files instead of using hard code values, but I'm not sure it is a good practice or not.
First I created a utility class:
public class ConfigValues
{
public static int Read(string key, int defaultValue){....}
public static string Read(string key, string defaultValue){....}
public static bool Read(string key, bool defaultValue){....}
...
}
The Read function tries to read value for the given key. If the key doesnot exist or the value has bad format, it returns the default value. And I'm going to use this class like:
public class MyClass
{
private int _age = ConfigValues.Read("Com.MyClass.Age", 0);
...
}
So that, we can make almost all variables in the application customizable.
Will it be a good practice?
Please comment it for free.

People who think you should make things configurable:
Some of the other answers
http://www.ebizq.net/blogs/decision_management/2007/04/dont_softcode_use_business_rul.php
Many good software development theories (I don't have links handy).
People who think differently:
http://ayende.com/Blog/archive/2008/08/21/Enabling-change-by-hard-coding-everything-the-smart-way.aspx (And the rest of his entries)
http://thedailywtf.com/Articles/Soft_Coding.aspx
http://benbro.com/blog/on-configuration/
http://jeffreypalermo.com/blog/hardcoding-considered-harmful-or-is-it/
The answer comes down to your requirements: why are you setting this value here?
Is it something that different users will want set differently? => config file.
Is it just a default value to be changed later? => Hardcode it.
Is it something which affects operational use of the program (i.e. default homepage for browser)? => Config file.
Is it something which might have complex impacts on various parts of the program? ... Answer depends on your userbase.
Etc. It's not a simple yes-it's-good or no-it's-bad answer.

Configuration files are always a good idea.
Think of the INI files, for example.
It would be immensely useful to introduce a version numbering scheme in your config files.
So you know what values to expect in a file and when to look for defaults when these are not around. You might have hardcoded defaults to be used when the configurations are missing from the config file.
This gives you flexibility and fallback.
Also decide if you will be updating the file from your application.
If so, you need to be sure it can manage the format of the file.
You might want to restrict the format beforehand to make life simpler.
You could have CSV files or "name=value" INI style files.
Keep it simple for your code and the user who will edit them.

Configuration file also allow you to update the values without doing another build to change a single value. This can be useful to have one build for all environments, with different configuration values (log levels, user names, etc.). Also, if you cache the values and periodically update from the file, it allows you to make changes on the fly while the application is still running. This may be overkill in some situations, but it can be very helpful in debugging certain issues.

Do:
Create a new C# project
Menu->Project->[Project name] Properties
Open Settings pane
Create your settings (it's strongly typed)
Usage:
class Program
{
static void Main(string[] args)
{
int setting1 = Properties.Settings.Default.Setting1;
Properties.Settings.Default.Setting1 = 43534;
Proerties.Settings.Default.Save();
}
}
Note that Properties is a namespace and you can import it so you can use Settings.Default.Setting1.
Here is a more detailed link.
If you use a windows forms application, you could change the Program.cs file to save all the changed settings when leaving application:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Add this line
Application.ApplicationExit +=
new EventHandler(Application_ApplicationExit);
Application.Run(new Form1());
}
//and this method:
static void Application_ApplicationExit(object sender, EventArgs e)
{
Properties.Settings.Default.Save();
}
}

Related

Where can I put static strings?

Im creating an Windows Phone app and I find myself writing the same MessageBox.Show("Same error message") multiple times. For instance
"Could not connect to server"
This happens when the user do not have internet access.
Is there somewhere I can put it so that I write the text once and fetch the same text all over the place?
I could write a static class, but maybe there is a file for this?
Is there somewhere I can put it so that I write the text once and fetch the same text all over the place?
Yes, there is a special kind of file specifically for this, called strings.resx. It lets you write
MessageBox.Show(strings.ServerNotFound);
instead of
MessageBox.Show("Server not found");
The added benefit (in fact, the intended purpose) of using strings.resx is that your application becomes easily localizable (see answer to this question): adding proper translations and setting the current locale is all it would take to change all strings that your application displays to users with their proper local translations.
If you want it to be multi-lingual in the end I'd go for the Resource.resx file.
If not, you can go for all kinds of solutions:
keep the string there where they make most sense, in the class where you use them
store them all together in a dedicated class
Like:
class MyClass
{
private static string MyString = "blah";
// other meaningful stuff
}
Or:
public class MyStaticStrings
{
public static string MyString = "blah1";
public static string AnotherString = "blah2";
}
You can create a static variable in the App.xaml.cs page in the App class, so that you can access it all over the application.

Resource Dictionary Vs .cs file

I have some constants that i would like to have at application level, like stored procedure names, user messages, and others. there is very less chance that i will ever change these resources.
Please let me know what is good practice for keeping constants in our application.
Is Resource dictionary is preferable over .cs file.
Regards
AA
For starters, you're on the right track thinking about this stuff at all. Magic strings and other magic values are bad for lots of reasons.
Here are some guidelines we use:
Constants are only allowed for things that are REAL-WORLD constant. If you need to use "My bonnie lies over the {0}" as a format string, you use a RESOURCE for that.
Things that might change, EVER, are not constants. You have a few options for this stuff.
If it isn't part of your logic, it doesn't go in source code. It goes in one of the following externals locations and gets referenced in source code so that you don't have to recompile to make a change.
We generally have three files per assembly, as needed:
First, a constants file. This is usually as simple as Constants.cs. Put your constants (AND readonly statics that are not compile-time constant and never change) in this file. You could also include things that are configurable but MUST have a default value.
internal class Constants
{
public const LogLevel DEFAULT_LOG_LEVEL = LogLevel.Error;
public static readonly string APP_NAME = Configuration.ApplicationName ?? "Test Application";
}
Second, a file that reads configuration values and returns them as static values. This is generally Configuration.cs and is responsible for return ALL configuration values. This saves you from having to recompile to change a connection string, deal with a setting, or something else. The actual values reside in places like an .ini file, web.config or app.config, database table, or other location outside the source code. If the following example you could smatter ConfigurationManager.AppSettings["ApplicationName"] all over your code, but then what if you want to change the key of that appsetting? You have to find an rename all the reference to it. Just take the extra 30 seconds to do something like this, and all Configuration.ApplicationName.
internal class Configuration
{
public static string ApplicationName
{
get
{
return ConfigurationManager.AppSettings["ApplicationName"];
}
}
}
Finally, one or more resource files. This is where we put things like icons, images, unusual fonts, localized (or just changable) strings for display purposes, etc...
There is no specific right way do do this stuff, but I think the above will give you a place to start.

What's the proper way to store and retrieve Application settings?

I'm predominantly a C# .NET 4.0 developer, and right now I'm reconsidering past approaches to storing and retrieving application settings.
In the past I've used a variety of methods, from simple 'flat' text files with tab separated key/values, to layered XML files, and a few other things in between. I've used in the past ( and am considering using again ) the built in App.Config/AppSettings classes, but there isn't any built in way to save data that you've loaded in from this source ( I could go into the difficulties I'm having in doing this but that's not the point of the question ).
The point here, is that all of these methods have their shortcomings, and while some work better than others, some are simpler to employ than others, and I am trying to nail down something that will be consistent and reliable.
My question, which will likely have a few valid answers so I'll be forced to pick the best one, is this: What if any built-in framework would 'you' recommend for both saving and loading data in and out of a settings file that can accompany the executable, or if not a built in framework, what standard would you recommend? XML? 'Flat' files? Stand-Alone Database?
Assume that the configuration itself won't be that large, and any real quantity of data will be read from a database ( or using some other technology ).
While Im a registry fan, and would rather have my settings there, with my c# apps I've used the settings that come built in - so under project properties you can define a load, and their default values, and then access them with
Properties.Settings.Default.<settingname>
and can set them too, so Properties.Settings.Default.HideDisabled = true;
and you can save them with
Properties.Settings.Default.Save();
Ive not had issues with this, but then, as you said, everything has a pro and a con.
Just yet another way (kernel32), it's not much about C# even C# 4.0 but as we have started list of variants it must be valid here
namespace Ini {
public class IniFile {
private string path;
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section,
string key, string val, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section,
string key, string def, StringBuilder retVal,
int size, string filePath);
public IniFile(string INIPath) {
path = INIPath;
}
public void IniWriteValue(string Section, string Key, string Value) {
WritePrivateProfileString(Section, Key, Value, this.path);
}
public string IniReadValue(string Section, string Key) {
StringBuilder temp = new StringBuilder(255);
int i = GetPrivateProfileString(Section, Key, "", temp,
255, this.path);
return temp.ToString();
}
}
}
A few applications I've worked on involve local databases and we used that database file to hold our settings too. It works, but something it just feels kinda wrong and it can be a problem if you would like to be able to modify a setting when your application is not running. (To bypass a crash or something alike.)
Most often I will just use an XML file stored in the Environment.SpecialFolder.ApplicationData folder and use a DataContractSerializer. It allows you to do some versioning, but most importantly, it's able to load and save XML files when certain properties on your settings object are new or non-existing. It won't crash the application and when you save your settings again it'll just save the latest version. I think it's clean, mean and simple.

config and settings component for C#

I'm starting to design a config and settings component for an application.
I need an easy way to read dictionary style settings and also a way to store simple arrays into a persistence level.
is there a commonly used component already available ? (something like log4net for logging)
what options should I look into ?
You don't really need to do that: .NET BCL already has everything you need.
Take a look at App.Config and the ConfigurationManager class.
If you expand the Properties folder in the SolutionExplorer you should find a Settings.Settings item. Double clicking on this will open the settings editor. This enables you to declare and provide initial values for settings that can either be scoped to the application or the current user. Since the values are persisted in Isolated storage you do not need to worry about what privileges the user is executing under.
For a wee example:
I created a new string setting with the name Drink and a TextBox named drinkTextBox. The code to assign the current value to the text box is:
drinkTextBox.Text = Properties.Settings.Default.Drink;
and to update the value persisted:
Properties.Settings.Default.Drink = drinkTextBox.Text;
Properties.Settings.Default.Save();
Depending on how flexible you want it to be, you can use the build in Settings designer (go to Project Properties > Settings) and you can add settings there.
These are strongly typed and accessible through code.
It has built in features like Save, Load and Reload
We'll often create a sealed class that has a number of properties that wrap calls to the the System.Configuration.ConfigurationManager class. This allows us to use the standard configuration managagement capabilities offered by the class and the app/web.config file but make the data very easy to access by other classes.
For example we might create a property to expose the connection string to a database as
public static string NorthwindConnectionString
{
get{return ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString
}
While it creates a wrapper around one line of code, which we usually try to avoid, it does make certain confiuration properties accessible via intellisense and provides some insullation around changes to the location of underlying configuration data. If we wanted to move the connection string to the registry, we could do so without major impact to the application.
We find this most helpful when we have larger teams or when we need to hand off code from one team to another. It keeps people from needing to remember what the various settings were named in the config files and even where configuration information is stored (config file, database, registry, ini file, etc.)
Building a dictionary in the standard settings
Using the standard Settings, it isn't possible to store dictionary style settings.
To emulate the System.Collections.Specialized.StringDictionary,
what I've done in the past is used two of the System.Collections.Specialized.StringCollection typed settings (this is one of your options for the setting type).
I created one called Keys, and another called values. In a class that needs these settings I've created a static constructor and looped through the two StringCollections and built the StringDictionary into a public static property. The dictionary is then available when needed.
public static StringDictionary NamedValues = new StringDictionary();
public static ClassName() // static construtor
{
StringCollection keys = Properties.Settings.Default.Keys;
StringCollection vals = Properties.Settings.Default.Values;
for(int i = 0; i < keys.Count(); i++)
{
NamedValues.Add(keys[i], vals[i]);
}
}
For noddy apps I use appSettings. For enterprise apps I usually create some custom config sections. CodeProject has some excellent articles on this.
For your scenario of key/value pairs I'd probably use something like this.

Where to store configuration information

I have a console application that I am rebuilding from C to C#. This application has to be able to support the legacy method of storing information like parameters from a command-line and parameters from a file (called the system parameters) that customize each run. The system parameters file is in plain-text with a simple key-value structure.
My questions are:
Should I combine these different parameters into a single Configuration object?
How would I call this configuration object from the code to store parameters?
How would I call this configuration object from the code to retrieve parameters?
Should this object be strongly-typed?
I will need access to this structure from a lot of different places in the code. What is the most elegant way to retrieve the values in the object without passing the object itself around everywhere?
I have a feeling that it should be a single, strongly-typed object and that it should be an instantiated object that is retrieved from a repository with a static retrieval method however I really want validation of this method.
I would use a single configuration object like the following:
using System;
using System.IO;
using System.Reflection;
public sealed class Setting {
public static int FrameMax { get; set; }
public static string VideoDir { get; set; }
static readonly string SETTINGS = "Settings.ini";
static readonly Setting instance = new Setting();
Setting() {}
static Setting() {
string property = "";
string[] settings = File.ReadAllLines(SETTINGS);
foreach (string s in settings)
try {
string[] split = s.Split(new char[] { ':' }, 2);
if (split.Length != 2)
continue;
property = split[0].Trim();
string value = split[1].Trim();
PropertyInfo propInfo = instance.GetType().GetProperty(property);
switch (propInfo.PropertyType.Name) {
case "Int32":
propInfo.SetValue(null, Convert.ToInt32(value), null);
break;
case "String":
propInfo.SetValue(null, value, null);
break;
}
} catch {
throw new Exception("Invalid setting '" + property + "'");
}
}
}
Since this is a singleton, it will create one and only one instance of itself the first time a public static property is referenced from the Setting object.
When the object is created, it reads from the Settings.ini file. The settings file is a plain-text file with a simple key : value structure that might look like this:
FrameMax : 12
VideoDir : C:\Videos\Best
The object uses reflection to discover each property and to store its initial value. In this example, two properties have been defined:
public static int FrameMax { get; set; }
public static string VideoDir { get; set; }
The code as written handles Int32 and String types. By adding additional case statements to the switch statement, you could easily add support for types like Float and Decimal.
To change a setting, you would use something like:
Setting.FrameMax = 5;
To retrieve a setting, you would use something like:
if (Setting.FrameMax > 10) ...
You'll notice that all the properties are strongly-typed. Also, you don't have to pass the Setting object around, as all the Setting properties are static and always available everywhere.
I hope this idea is helpful.
I like using Settings. These can be generated automatically either by creating a settings file using the Add New File dialog box, or by adding a default settings file from project properties.
Each setting may be in user or application scope, which controls whether or not the user can change them or they are restricted to their default values. They are easily saved with the Save() method and loaded automatically into the static Default property.
This class seems to be for application or user-based settings. I'm looking for per-run settings. Would you still recommend using this class in that case? – x97mdr
Yes. If you have both user/application based settings and per-run settings you should use two different classes - the normal (saved) settings and the per-run settings.
As long as you don't save the per-run settings, you should be safe and settings are still quite easy to use. These are static settings though. If the same application run needs several instances - this is the wrong approach.
I find that whenever I have to deal with a legacy system, sticking with the old format almost always works best. Often times there are other people using the legacy formats for other tasks (like automation of the app, for example), so if you recode the way the application handles inputs, you might break other systems.
On the other hand, if you are pretty confident that you know all the people using the system, and they tell you that they don't care if you change these types of things, I would probably move everything to XML. Besides all the nice features of XML from an application point of view (like being in ASCII so it's easily modified by humans, being self-documenting, etc ...), XML is also time-saving, in that you don't have to write your own I/O or parser. There's already a wide variety of libraries out there, particularly in .NET 3.0/3.5, that do very well. (As you're moving to C#, I'm guessing you're already thinking along these lines :)
So ultimately, you'd have to base your decision on cost-to-implement: if you lower your cost of implementation by moving to XML or similar, make sure that you don't raise other people's cost of implementation to move to your new application framework.
Good luck!
XmlDocument - you can generate a class definition using XSD.exe

Categories

Resources