How can I distinguish user settings by name in C#? - c#

Following CodeProject and StackOverflow.105932 (and a few others, e.g., StackOverflow.1873658 and MSDN articles) I have a main form whose Size, Location and WindowState are saved in and read from Properties.Settings.Default.<name>, e.g., Properties.Settings.Default.WindowState = WindowState; and this works great for this one form. EVERY code example I turn up seems to think there will be one and only one global setting for WindowState, none of them say how to distinguish these settings per instance.
However, I wrote the code in a superclass of the Form because I want all the Forms IN THIS APPLICATION to inherit from that class so they are all able to save/read their own size, location and state.
What I'd LIKE to do is simply replace the word "Default" in the key path above with the class name of the inheriting form. Here is pseudo code that would be great if it worked (it doesn't, and I cannot find a variation that does):
Properties.Settings[this.ToString()].WindowState = WindowState;
How can I do this correctly, reusably, maintainably, entropy-proof?
Edit: Would "config sections" be the answer? (Maybe create a section for each Form subclass?)
Edit: No, not config sections but I think this class must be part of the correct solution.

Well, at its core that's just not the way settings work in .NET by default. The settings file for settings with Scope = User are carefully hidden away in a private AppData folder with an unspeakable name. A name that's created by hashing various properties of the main EXE, including its name, location and [AssemblyVersion]. Important to prevent programs from overwriting each others settings file by accident. There is no documented way to get to that file from another program. Mostly because you have no good way to guess these property values for another program.
There are workarounds for that, instead of the default LocalFileSettingsProvider class you can create your own class derived from SettingsProvider. It's a bit painful, System.Configuration is not exactly the finest namespace in .NET. A good way to get started is by using the RegistrySettingsProvider SDK sample.
Or just punt the problem, just create your own XML file that you store in an AppData folder that you can always get to from any app. Which is in general a good idea because you'll tend to get burned by versioning problems when many apps share a common data file. You'll want to declare an XML-serializable class in its own assembly that stores these properties. With a heavy "Do not change without talking to me first" comment on top.

Related

Settings specific to a class

I have a class where I retrieve certain settings from a database (usernames and passwords). This database is sitting on a network, and it means that if the passwords are changed, I can simply change it in the database, and all the applications that use this class will still work.
I am fully aware of the pros and cons of storing usernames and passwords in a database and in a separate location. I don't want to discuss those, please.
The class has a hard-coded static string that is the path to the database. It is a fully qualified network name (not just the drive letter). I did this because we had an issue where our network DNS got screwed up, and drive letter mappings stopped working, and some people have different drive mappings anyway.
We recently had our server moved, so I now need to go through and change these hard-coded strings.
I was thinking that I should store the path in a settings / configuration file instead. I considered "application.settings", but it is not an application setting; its specific to the class. Is there a preferred way of doing this in the existing .Net framework (this is a C# issue)?
I could simply have a small text or XML file that sits in the application directory, which is probably fine... is there an existing framework namespace or open-source code snippet that someone knows of that I can use?
I think, if you want class specific configuration, you should try to have those class instances, configuration driven. Another way of thinking but; Defining a something in a configuration file, will create an instance of the defined classname.
For example: Create a section, and call it, <Modules> and create items in like: <module type="<namespace>.DBConvertor" param="username=root;passwd=whatever"> This type will be created at startup (you need some coding here). And it's even possible to create more than one instance simultaneously with it's specific configurations.
This kind of configuration is already implemented:
You might take a look at this: "How to: Create Custom Configuration Sections Using ConfigurationSection" https://msdn.microsoft.com/en-us/library/2tw134k3.aspx
And creating instances from typenames, use the Activator class.
Besides that, there are many module/plugin libraries, (like Managed Extensibility Framework (MEF) https://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx but could be a little over the top in this case).

Get application settings without file access

I have an app.config which is working fine.
But I also have a tool for automated testing, that runs some tests in environment without any file access. So I have to read a config file from string (or memory stream), but without mapping it physically because there is no access to file system from this automatic testing process.
In real life, of course, config file is stored somewhere, but for automated testing purposes I need some workaround to read a config file from string stored in memory. Is it even possible? I googled a lot, but the only thing I found is Save it as temp file and then read, but it's not my case.
Avoid a direct dependency from your class on app.config or any other file. Your class doesn't need app.config or Properties.Settings. It needs the values contained in the those files..
If you create a workaround for testing purposes then you're testing a different version of your class. That's the inherent problem - direct dependency on these files isn't testable. It doesn't mean that they're bad in some way or that we shouldn't use them, only that the class that requires the values should not read them from the file.
An ideal solution is constructor injection, a form of dependency injection. Provide the value to the class in its constructor and store it as a field. That way when the class is created it always has the values it needs.
At runtime you can use a dependency injection container - here's a walkthrough on setting one up for WCF. You're likely in a different project type, but the concepts still apply.
But for testing, it's as easy as creating a class and passing whatever value you want to use into the constructor. It's impossible to test with different values when the class reads from settings but it's easy using constructor injection.
Without the configuration file you'll have the default settings. You may override the default values:
Properties.Settings.Default["PropertyName"] = NewPropertyValue";
(Set the correct access modifier on your Settings class and use the correct namespace if it is in a library)
As first option I would go for Settings file in your case.
Even your user won't be ablle to access settings file content. Then it will return a default value for a particualr property.
You can try creaty a silly console app
static void Main(string[] args)
{
Console.WriteLine(Settings.Default.MyProperty);
Console.ReadLine();
}
were you set the your value for MyProperty on the Settings Tab of you Project Properties.
Then you can build your solution, open the binaries folder and delete your exe.config file and you will see that the app will be use default values.
As second option you can use command line arguments. could also be an option for you. (Here the article about some tricky case for command line arguments Backslash and quote in command line arguments )
Third option could be placing your file at c:\users\your app user \AppData\Roaming\YourAppName folder. here you should be granted for file access even for restricted user
For education reason I would also reccomend to look at this article: https://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(ApplicationSettingsOverview);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5)&rd=true
Maybe you find the "Load Web Settings" option nice.
Another palce for investigation could be

Can someone explain Settings to me and how to use them in C#?

Basically something I'm working on requires me to use Settings. I've never used Settings when it comes to C# and VS and the guides I've tried reading on the internet aren't really clearing it up for me. So I've got a few questions and if anyone could answer them then that would be brilliant.
What is a setting and what's it's purpose?
I've declared some settings, now how do I use them in my code?
Can I declare a setting as a variable or are they already variables that can be used?
An example is that I've got these codes in my Settings "BL,CC,CW,DX,DL,DU,F2,HA,JL,LD,PR,PS,S,SC,SF,UD,WL,ZC,ZD", they're called Codes
how can I use these Codes in the context of my code that when something is equal to one of these codes, do something else?
Using Settings in C#
What is a setting and what's it's purpose?
The .NET Framework [..] allows you to create and access values that are persisted between application execution sessions. These values are called settings. Settings can represent user preferences, or valuable information the application needs to use. For example, you might create a series of settings that store user preferences for the color scheme of an application.
How do I use them in my code? Are they already variables that can be used?
You can read both application-scope and user-scope settings at run time with the Properties namespace. The Properties namespace exposes all of the default settings for the project by using the Properties.Settings.Default object. When writing code that uses settings, all settings appear in IntelliSense and are strongly typed. Thus, if you have a setting that is of type System.Drawing.Color, for example, you can use it without having to cast it first, as shown in the following example:
this.BackColor = Properties.Settings.Default.myColor;
As for your specific question, you might want to look into something like string.Contains().

Type name does not correspond to file name?

This warning message is popped up when my mouse is over my class name, I can understand that the file name should be named exactly as the class name (or vice-versa) (which is defined in the cs file). That will be OK and of course good to follow but what if I intend to define more 1 class in a cs file? Or I shouldn't do like that?
I don't like any warning message, it seems to mean that I'm doing thing abnormally and in a non-standard way.
As comments point out it is not comment put by C# compiler (or Visual Studio).
There is no restrictions in C# on number of classes per file or if class/namespace should match file/folder name (unlike Java or ActionScript).
It is considered good practice to have one class per file (not counting nested classes) and somewhat match folder names to namespaces. This makes code easier to search and easier to find files corresponding to particular classes.
As for length of classes again there is no technical restriction, but long classes generally mean too many responsibilities in one class and as result not recommended. Generally there is no reason not to have many small classes in individual files.
You need to come up with style that works for you/people you work with and try to stay with it. Most code analysis/style checking tools (like ReSharper) are very flexible in style checking, so you often can adjust rules to your liking.
The first class in the file should be named same as the filename. If you need other classes that are only used by this class you can put them below this top level class and you will not get any warnings.

basic question on C# - do I need a namespace?

I am a Java developer, totally new to C#. I am currently writing a DLL for distribution across my organization. It is a very simple library containing a couple of classes and I do not see any real use in putting all of them into some namespace just for the sake of it. Do I really have to use a namespace? If so, why? Is it some kind of a best practice?
Do you need one? No. Should you have one? Yes. It'll help prevent clashes with identically named classes in other namespaces without having to resort to the (IMHO) ugly use of global::.
For throwaway test apps (e.g. checking Stack Overflow answers), I don't use a namespace. For anything else, I do. It's just an organization thing - if you're going to reuse code, it's helpful to separate it from other code you're also reusing in the same context. What I mean is, if you're creating an app using LibraryX and LibraryY, it's useful to be able to differentiate between them within the app. It's possible that they both use the same class names, for example - which will make the code ugly if you don't use namespaces.
Aside from anything else, if you're coding with Visual Studio it's actually more work not to include a namespace - you've got to modify the project to give it an empty default namespace.
There is no need to have a namespace. However developer studio expects you to be using a name space. For example, when you choose to add a class to a project developer studio will:
Create a file for the class
Add the file to the project
Create an empty class (in the above file) that is in the project’s default namespace.
A “project’s default namespace” is a developer studio concept not a C# concept and is set in the properties of the project.
As you are creating a dll for others to use, it will be a lot easier for the users of your dll if you have a name space:
People expect you to have a namespace (so may be confused if you don’t)
Namespaces make it a lot easier for your users if you have class (or enum etc) that is named the same as another class in any dll they are linking to.
Therefore I don’t see a good reason not to use a namespace.
My vote for "yes" i think it is good habit to use namespace. you can not be sure that people won't use same class names.
To respond to your comment about naming a class the same as it's namespace, read a little bit of the following article.
Short version: don't do that.
http://blogs.msdn.com/b/ericlippert/archive/2010/03/09/do-not-name-a-class-the-same-as-its-namespace-part-one.aspx
Basically System is a root namespace in asp.net C#.
In .net every programs is create with a default name space. This default namespace is called global name space. But program itself create any numbers of namespace, each of unique name.
learn more
http://asp-net-by-parijat.blogspot.in/2015/08/what-is-namespace-in-c-need-of.html

Categories