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.
Related
This is rather general question, but it relates to overall application design. I'm trying to create application that follows class design standards and I'm struggling with one aspect that is how to store information internally.
For example I can create a class for a Movie with couple fields:
title
year
director
So when I parse xml files that holds this metadata I would load them into a public List. I'm not sure if this is a right approach? Since List is an instance of an object, maybe it does not belong in a class that defines Movie?
It is public list it would be available in other parts of application.
I do not see any point of parsing xml files multiple times during application activity. The same goes for accessing database like SQLite.
I looked at Singleton design and I'm not sure if that is a right approach? Plus based on Singleton samples I viewed, I do not know if I can define fields that I mentioned before.
So, my question is. How do you deal with metadata or file paths from scanned folder? Where do you keep this information inside your application?
Thank you
The class which parses the XML file shouldn't store the result. If that class parses a list of movies, it should just return an IEnumerable<Movie>, and then the caller of that class can store the result wherever it wants to.
This is a pretty general question and there are a number of ways to do it depending on your NFRs. The following is a pretty basic way that should be forward compatible with a number of approaches.
Declare the list within main program scope as an IList<Movie>.
Write a class that implements IList (e.g. class MovieList:IList<Movie>) that exposes the data you need. It can cache it if you want. It doesn't have to. For now, write the simplest code that could work.
Later, in the main program, you can change the declaration of your IList to use an IoC container to instantiate the IList (e.g. _myList = Container.Resolve<IList<Movie>>. That way you can substitute different data providers, or substitute a mock provider for unit testing.
Later, you can change the implementation of MovieList to include caching, or store the data in a DB, or whatever you want. Or you can totally rewrite it in a new class and change the configuration of your IoC container to point at the new class. You will have all sorts of options. (The decision to cache or not to cache will ultimately depend on NFRs such as storage capacity, performance, and concurrency/ACID)
The point is to write down the bones of what your program truly needs, and worry about the details of where and when to store stuff later.
I don't think it is a good idea to simply store the whole list in a global variable without some kind of abstractification.
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).
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.
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.
I've run into this issue quite a few times and never liked the solution chosen. Let's say you have a list of States (just as a simple example) in the database. In your code-behind, you want to be able to reference a State by ID and have the list of them available via Intellisense.
For example:
States.Arizona.Id //returns a GUID
But the problem is that I don't want to hard-code the GUIDS. Now in the past I've done all of the following:
Create class constants (hard-coding of the worst kind.. ugh!)
Create Lookup classes that have an ID property (among others) (still hard-coded and would require a rebuild of the project if ever updated)
Put all the GUIDS into the .config file, create an enumeration, and within a static constructor load the GUIDS from the .config into a Hashtable with the enumeration item as the key. So then I can do: StateHash[StatEnum.Arizona]. Nice, because if a GUID changes, no rebuild required. However, doesn't help if a new record is added or an old one removed, because the enumeration will need to be updated.
So what I'm asking is if someone has a better solution? Ideally, I'd want to be able to look up via Intellisense and not have to rebuild code when there's an update. Not even sure that's possible.
EDIT: Using states was just an example (probably a bad one). It could be a list of widgets, car types, etc. if that helps.
Personally, I would store lookup data in a database, and simply try to avoid the type of hard coding that binds rules to things like individual states. Perhaps some key property of those states (like .ApplyDoubleTax or something). And non-logic code doesn't need to use intellisense - it typically just needs to list them or find by name, which can be done easily enough however you have stored it.
Equally, I'd load the data once and cache it.
Arguably, coding the logic against states is hard coding - especially if you want to go international anytime soon - I hate it when a site asks me what state I live in...
Re the data changing... is the USA looking to annex anytime soon?
I believe that if it shows up in Intellisense, then, by definition, it is hard-coded into your program.
That said, if your goal is make the hard-coding as painless as possible, on thing you might try is auto-generating your enumeration based on what's in the database. That is, you can write a program that reads the database and creates a FOO.cs file containing your enumeration. Then just run that program every time the data changes.
This cries out for a custom MSBuild task. You really want an autogenerated enum or class in this case; if the IDs are sourced from a database and can/will change, and are not easily predicted. You could then put the task in your project and it would run before each build updating as necessary.
Or start looking at ORMs :)