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.
Related
We have a system that manages generic physical resources. There are over 500 individual resources. The system is used for many different things and to make the software easier to write we use aliases.
For example, a physical resource TG67I9 is given an alias of "RightDoor". When code is written RightDoor is used instead of TG67I9 making the code more readable. This alias list is loaded as a text file with references to resources and their aliases. This system uses literally hundreds of different alias lists to reference the same physical resources.
This type of setup has two major shortcomings. First, when resources are called using their aliases, they are passed in as strings. Door.Open("RightDoor") for example. This does not give any tooltips or smart anything making the code more difficult to write. It basically requires constantly referencing the alias list. Is it RightDoor or Right_Door or right-door or... you get the idea. The second is that there is no validation of parameters until execution. All the compiler knows is that a string is passed in and then it's happy. Only when the code is run, the function tries to access the resource through its alias and fails because it can't find right-door because it's supposed to be RightDoor. An error is displayed. This requires tedious debugging and running the code over and over to weed out any bad aliases.
Is there a better way to do this? Such that an alias list can be made with a cross-reference of physical resources to their alias names and after the list is made that tooltips could appear suggesting resources. (Assume that a new system could be written from scratch)
I'm using the latest .NET with VisualStudio 2017 and C# to write the code.
The simplest approach is most likely a "string enum":
public class Resources {
public const string
LeftDoor = "TG67I8",
RightDoor = "TG67I9";
}
Sample use:
Door.Open(Resources.RightDoor);
Hovering over .RightDoor in VS shows a tooltip (constant) string Resources.RightDoor = "TG67I9"
Right-clicking .RightDoor and selecting Find All References will show where the variable is used.
Another option can be adding the strings in the Resources section of the Project Properties, and then:
using YourProjectNameSpace.Properties;
...
Door.Open(Resources.RightDoor);
That is a bit slower, because the resource(s) are retrieved at run-time, but allows to load the resources from a custom external file separate from the executable.
Use a static class with constants. I have done the same many times and still do. Plus .NET does this as well.
public static class PhysicalResources
{
public const string One = "Uno";
public const string Two = "Deux";
// ...
}
What are the best practices for using the Properties.Settings.Default config settings in C#? I see it commonly, but I often don't know when to utilize it vs. when I should just hard code values. Thanks!
Basically, I try to avoid hardcoding values in code, mainly because if there's ever a need to change their value it requires a re-compile of the app.
It's usually beneficial to have some sort of common object that exposes all your settings via public properties so that you are referencing the settings the same way throughout the app.
Example:
public static SomeReferenceClass
{
public static string TimeOfDay { get{ return Properties.Settings.Default.TimeOfDay; }}
}
Then Later on to call it
SomeReferenceClass.TimeOfDay;
My rule of thumb has always been that if the values of the properties need to change without modifying the code then make them an external/configurable property. If you will never need to change their value, then they're a constant and can be hard-coded.
Basically, if these values need to be configured/changed put them in Properties.Settings.Default. You can hard code constants.
personally, I use the default setting when the user or application setting are not specified or persisted.
I'd never hardcode a setting that might change based on any number of variables such as environment, user, application, or whatever.
I generally create settings providers that implement an interface. That way, you can easily change out how to gather your configuration settings without changing the business logic.
I have a resource file in a Class Library project. I'm using this resource file to hold various messages the user may end up seeing.
For example, the name of the resource is "InvalidEmailAddress" and the value in the en-US resource file is "Invalid Email Address".
When I call the ResourceManager's GetString(string) method I am doing this:
return resourceManager.GetString("InvalidEmailAddress");
However, this seems really bad to me. What if somebody changes the name of the resource? Now my statement will return a null value.
Is there a way around this issue?
UPDATE: Localization is an important factor here. The resource manager is used in order to ensure I can change the culture and get appropriate string values.
You can instead use an automatically generated class - the magic string constants will be removed from the code and replaced with strongly typed access methods. VS names this file ResourceName.Designer.cs and updates it every time resx is modified in VS.
Sample of a generated method:
internal static string String1 {
get {
return ResourceManager.GetString("String1", resourceCulture);
}
Note: while creating this file is the default behavior when you add a new resource in VS, you may have disabled it or you may have tried to use the generated resource outside the assembly. In that case, make sure to set the "Custom Tool" property or resx file to "PublicResXFileCodeGenerator" or "ResXFileCodeGenerator" (later if you use resources only inside a single assembly). (Thanks #dbaseman for comment).
When you create a Resource, it will be generated strongly typed in the Resources namespace.
You can access it by Resources.ClassName.InvalidEmailAddress where ClassName is the name of your Resource (resx) file.
What will be the Regular Expression to get all the property and variables names of any class in c#, I want to parse the *.cs file. that is i want to select any *.cs file as input and it should get the property name of that selected class, as an output.
can any one help!!!....would appreciate for any help i tried very much but not got the actual result every time class name is coming instead of property.
thanks
Jack
There's no way you're going to be able to get exactly what you want with a regular expression because you need semantic context, not just string parsing.
For example, a good first attempt at finding all of the field and property definitions in a C# file might go something like this
^\s*(?:(?:private|public|protected|internal)\s+)?(?:static\s+)?(?:readonly\s+)?(\w+)\s+(\w+)\s*[^(]
That will match properties (public int Foo {...}) and fields (private int foo;) but not methods (protected void Bar()).
The problem is that a regex engine has no concept of the context within which those tokens appear. It will match both foo and bar in this code:
int foo;
void Stuff()
{
int bar;
}
If you happen to know that your code file follows some coding standards, you may have more luck. For example, if you enforce a style rule that all class members must have access specifiers, then you can make the private/public/etc part of that regex non-optional; since those are only permitted at the class level, it will filter out local variables.
There are other options, none of them too attractive at first glance. There is persistent talk from the C# dev team about exposing the C# compiler as a service in some future version of .NET, which would be perfect here, but I wouldn't expect that any time soon. You could purchase a third-party C# parser/analyzer like this one (caveat: I have zero experience with that, it's just the first Google hit). You could try compiling the .cs file using csc and examining the IL, but you'd need to know all of the third-party references.
My idea is to avoid magic string keys in my Asp.Net MVC application.
To do so, I want to create string constant keys to be shared in the application.
For example, I can write TempData[MyClass.Message] or TempData[MyEnum.Message.ToString()] instead of TempData["Message"].
public class MyClass
{
public const string Message = "Message";
}
and
public enum MyEnum
{
Message,
Others
}
My questions are: Which is the better way to avoid magic string keys? Using string const keys in a class or using enumeration together with ToString()?
It is up to preference and usage.
You are able to accept the enumerated values in a strongly typed way:
public void SomeFunction(MyEnum someValue)
{
}
Or
TempData[MyEnum.Message]
With const strings, you can't.
You also have a built-in way to enumerate the values in an enum.
There is a third option which you haven't presented, and that is to place your "constants" in your configuration settings (App.Config). This will let you configure them after compile time. You might not need this now, but you might in the future, so it is worth considering.
One of these may be better for globalization purposes. I'm not sure which, since I've never globalized an app. Whichever works in satellite assemblies, I assume.
Basically, it comes down to what TempData is, and how you intend to use it.
You should go for const strings as it can containt spaces/special chars as well, if those are your requirements. Otherwise change TempData to Dictionary<MyEnum,object> which is better approach.
I know this has been answered, but I want to throw in my thoughts here. You're focusing too closely on the mechanics and not the problem you're having - which is "how do I get away from breaking my application when I decide TempData["Message"] should actually be Session["Alert"]" (or something like that.
Magic strings do not apply to dictionary keys - they apply to messages sent to routine that does something based on the string value. Something like "SetStatus('current')" would be magical.
What you want to do here is to use a centralized method for handling messaging. Create yourself a helper class and call it "Messaging" if you like - ir get all Railsy and call it "Flash". Then, you could do something groovy like "Flash.Message("Hi there")" - this keeps the mechanism hidden (as it should be) and you're not worrying about those silly dictionary keys.
You can also expand this - "Flash.Alert('Oh NO!')" - etc.