I'm working on a WPF Prism application and have two situations where it would be preferable to have strings that are accessible across the system.
The first are the names of my views. The names of the views are used when setting up the view, as well as navigating to the view. I want to avoid typos in the view names. There's also a chance that these names could change in the future, and it's not a good idea to rely on memory to find every instance of where that view is used. The second case is for the name of different claims, in the sense of claim based authentication.
Should I be creating these as constants, despite the possibility of the strings changing? Perhaps making them readonly would be preferred? Thanks for your input!
I would definitely use storage class in common assembly for this. Something like this:
public static class Claims
{
public static readonly String View = "http://schemas.mycompany.com/claims/view";
public static readonly String Edit = "http://schemas.mycompany.com/claims/edit";
public static readonly String Upvote = "http://schemas.mycompany.com/claims/upvote";
}
Microsoft uses similar approach
That leaves only one dilemma: const vs readonly. I'd recommend to use readonly in your case, because you said there is a possibility of changing. Const should be used only if data is actually constant, because constants are not referenced, but copied to each referencing assembly. E.g. if you define constants in assembly A and use them in assembly B, then if you change them in A, you'll have to recompile B, otherwise B will keep old version of these constants.
I would create a class with all the constants and keep all the constant values there. You could create a project that is shared among all other projects.
A common assembly storage class may be simple enough for your needs, but you may want to consider using a .resx file. It's essentially a XML format file where you hardcode your strings and you can then reference inside your code. MSDN Documentation
Here's some compelling reasons to use them:
Resource files give you an easy way to localize/internationalize your .net applications by automatically determining which language resx file to use based on the user's locale. To add more languages, simply add another translated resource file.
Resource files give you a central location to store your strings, files and scripts and refer to them in a strongly-typed manner (so the compile will break if you reference them improperly).
Resource files can be compiled into satellite assemblies, making it easy to change up the resources in a production application without having to recompile the whole thing.
What are the benefits of resource resx files?
You can read from the resx as so:
var <Variable Name> = Namespace.Properties.Resources.<Resource Name>
I'm confused with the answers given. All UI strings should always be in the string table. That's what its there for. Its accessible system wide. Plus you can localize.
Related
I have signed all my assemblies with strong name.
Now I have to allow all internal assemblies that are friends with unit tests to share the publickey info.
This can be done using,
[assembly: InternalsVisibleTo( "MyProject.UnitTests, PublicKey=XXXXXXXXXXXXXXXXXXXXXX" )]
I am re-using the same public key across all projects.
I have a global CommonAssemblyInfo.cs that is linked to all projects and each project apart from referring to CommonAssemblyInfo.cs refers to a local one "AssemblyInfo.cs" as well.
I want to keep the public key value in CommonAssemblyInfo.cs and reuse the same value in all Local "AssemblyInfo.cs" to be used in "InternalsVisibleTo" attribute to reduce duplication and improve maintainability.Is there any way to do this?
One option is that I can place the public key in a static common class and reuse them from all AssemblyInfo.cs but, this needs an additional reference to the common project.
You can use some placeholder for public key inside the assembly attribute in CommomAssemblyinfo.cs file and that can be replaced using python script(I prefer that) or some other tool while creating installer.
Please refer to the link to know more how to replace placeholders in python script.
I have a newb question. I have a winforms application that has a number of classes that referenced a number of UNC network paths. I started to notice I had a bunch of string duplication and then started trying to weed them out by consolidating them into the classes that just make more sense to have them. I was then referencing the class with the string I needed each time I needed to get the value of the string but I'm sure this was a sloppy way to do it.
Now I've settled on making a single class ("StringLibrary") and am referencing that class in each class I need to pull strings from. This seems much more efficient than what I was doing before, however, I'm still not sure if this is a good way to do it in general.
Is there a better way (i.e. more standardized way) to consolidate a group of strings or values in c#?
It depends on whether the strings are configuration or more permanent. For network paths, you may want to put them in your app.config file (see What is App.config in C#.NET? How to use it?), since they may change from time to time, or differ between deployments (and you do not want to recompile your code for every site) Depending on the nature of the data, you may alternatively want to store it in the registry or in a database.
If it is something more tightly tied to your code, like names of controls on a form, or names of columns in your database. Then you may want to centralise their definitions as you suggest, and reference them all from there. When there are a lot of them, your may want to split your StringLibrary into more classes with more relevant names (e.g. if you are speficying names of columns in your database, then you may want to create such a static class for each table in your database) If you take this approach, and since you are new to C# it may also help to read Static readonly vs const to decide if you want them to be const or static readonly.
These could be added to an application config file/ web config file,
resource files and/or settings files.
This way you can administer these strings, should they change, without having to re-build your application and also apply transformations (if in an app.config/web.config) when performing releases to different environments/deployments.
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.
I was often wondering about the right way to do this:
For example, in my program I have around 100 constants (or enums) that are used in some calculation. They should preferrably be stored in one place. They can be grouped hierarchically, for example:
System3 / Rules / Rule7 / ParameterXY / MaxAverageValue
Naturally, I want those values to be accessible while coding, so storing them in some kind of ressource is not really an option.
As far as I could tell, this can be done with:
very long constant names
nesting classes
namespaces
Using names is quite ugly, and it's not really well maintainable. I find nesting classes a nice way to do it, but some stylecop/fxcop rules forbid that, so this must be "bad" in some way. Lastly, I find the suggested alternative, using namespaces, not terribly nice neither. Imho it creates masses of folders and files that each contain almost nothing. And I don't like when 50 sub-namespaces pop up in the assembly reflector.
So.. how do you do this kind of task? What would you suggest?
very long constant names
This is sort of gross, but at least it is discoverable. All your code would reside in the same place so you wouldn't have a problem finding it.
I find nesting classes a nice way to do it, but some stylecop/fxcop rules forbid that, so this must be "bad" in some way
One reason it is is bad because automated code generation/code inspection tools are harder to work with. Another reason is that it is harder to discover these with Intellisense.
The most important reason this is bad is because a nested class should be strongly associated in an object-oriented dependency sense for the layout be make sense logically. In all but some rare cases (e.g. Enumerator classes) it won't make sense. In your case it also doesn't make sense because your classes don't really have any behavior or object orientation at all - they're just a hierarchy of constants.
Namespaces
For the problem you described, this is the best way to handle it. You get the least clutter per-level, and you get Intellisense while typing so you can see what you're narrowing down to while descending through the hierarchy.
Imho it creates masses of folders and files that each contain almost nothing
If you really need a huge pool of constants, and it doesn't make sense to bind them to other parts of your application, then this is one of the rare cases that I'd abuse the one-file-per-class and one-folder-per-namespace rules. The only reason you're even stuffing them into classes at all is because .Net doesn't have support for global variables.
Another suggestion
Do you have domain-specific objects that these constants belong on instead? E.g. is there any logic related to the System3 / Rules / Rule7 class? Is that not some sort of actual business rule that you should embody with its own class?
If you can arrange your code so that you have a thicker domain model, then the most logical place to put your constants is on the classes that embody the corresponding domain logic.
If it doesn't make sense to have a thick domain, you have fully generic rules processing, and you are relying on constants to feed your business engine logic, then you have a data-driven application. This means you should store your data in configuration files, not in code.
How often is each constant re-used in multiple methods? You could consider reorganizing your constants. If you still find yourself with huge numbers of constants, try putting them in a static class with read-only properties.
If you just need a good place to look at them all in one place, you could also look at storing them in the app.config file and you can access them through AppSettings and the ConfigurationManager class.
Well the way I do this is to have a sealed file called Constants.
so
public sealed class Constants
{
//for e.g.
//Sessions
public const string APPSESSIONKEY = "AppType";
}
Than I use this in the rest of my project and the importance here is what you will name it as it will help you remember it and make sense when you need it.
By calling it in your code.
Constants.AppSessionKey
You could also
Create an Assembly whose only purpose is to hold constant values for the project. Every other Assembly should then reference this one. Following DRY and KISS, since adding references is simple enough. Main problem here is recompilation.
We use Resources files with a custom T4 template that generates a static class hierarchy with readonly string fields for the values.
The keys in our Resource file are separated with '.' to build the hierarchy.
We can have separate resource files that are compiled into one class hierarchy.
I know that nested classes is not recommended but in my opinion, for a situation like this it is the nicest solution.
I have lots of global read only strings (around 100) that I am using in my application that will never change. I have been trying to think of the best solution that is easy to code and doesn’t have too much impact on performance. I need the strings to be used throughout the application like the example below, where Relationship is just a category in which the value is grouped and Alternate is the string value itself.
Relationship.Alternate
I have thought of creating static classes with static read only fields, static classes with const fields, implementing a Singleton pattern and even creating and parsing enums in a helper method. Can anybody provide some good advice on the best way to tackle this problem.
How about using resource files?
They are typed, easily accesible from your code at run-time, easily editable without need to recompile, and support any string content (i.e. not like enums, which only support identifier-like strings).
For example, you can add a resource file named GlobalStrings.resx to your C# project, and then add a string named Relationship_Alternate to that file. You can type any value you want for that string. In code, you would access the string value as:
GlobalStrings.Relationship_Alternate
Since those are identifiers validated at compile-time, you can guarantee that all your strings will load successfully at run-time.
Hope it helps.
Why dont u put them in enum which can make it memory efficient as well as readable along with less error prone
if they are going to be set at compile time you can try putting them in appSettings (in your web.config or app.config). This would typically apply for connection strings etc. If they are going to be set at run time, depending on some other value, you can go with static class & static read only fields
Edit:If you want them strongly typed, you can also use settings file . see MSDN article
You should consider using a resource file. See MSDN or solution B in this CodeProject article.