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.
Related
I have a set of strings like this:
System.Int32
string
bool[]
List<MyType.MyNestedType>
Dictionary<MyType.MyEnum, List<object>>
I would like to test if those strings are actually source code representations of valid types.
I'm in an environment, that doesn't support Roslyn and incorporating any sort of parser would be difficult. This is why I've tried using System.Type.GetType(string) to figure this out.
However, I'm going down a dirty road, because there are so many edge cases, where I need to modify the input string to represent an AssemblyQualifiedString. E.g. nested type "MyType.MyNestedType" needs to be "MyType+MyNestedType" and generics also have to be figured out the hard way.
Is there any helper method which does this kind of checking in .Net 2.0? I'm working in the Unity game engine, and we don't have any means to switch our system to a more sophisticated environment with available parsers.
Clarification
My company has developed a code generation system in Unity, which is not easily changed at this point. The one thing I need to add to it, is the ability to get a list of fields defined in a class (via reflection) and then separate them based on whether they are part of the default runtime assembly or if they are enclosed within #if UNITY_EDITOR preprocessor directives. When those are set, I basically want to handle those fields differently, but reflection alone can't tell me. Therefore I have decided to open my script files, look through the text for such define regions and then check if a field is declared within in them, and if true, put it in a separate FieldInfo[] array.
The one thing fixed and not changeable: All script will be inspected via reflection and a collection of FieldInfo is used to generate new source code elsewhere. I just need to separate that collection into individual ones for runtime vs editor assembly.
Custom types and nested generics are probably the hard part.
Can't you just have a "equivalency map to fully qualified name" or a few translation rules for all custom types ?
I guess you know by advance what you will encounter.
Or maybe run it on opposite way : at startup, scan your assembly(s) and for each class contained inside, generates the equivalent name "as it's supposed to appear" in your input file from the fully qualified name in GetType() format ?
For custom types of other assemblies, please note that you have to do things such as calling Assembly.LoadFile() or pass assembly name in second parameter to GetType() before to be able to load them.
See here for example : Resolve Type from Class Name in a Different Assembly
Maybe this answer could also help : How to parse C# generic type names?
Could you please detail what is the final purpose of project ? The problem is a bit surprising, especially for a unity project. Is it because you used some kind of weird serialization to persist state of some of your objects ?
This answer is more a few recommandations and questions to help you to clarify the needs than a definitive answer, but it can't hold in a single comment, and I think it provide useful informations
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 am considering using NO SQL databases such as MongoDb, RavenDb or any other ones recommend I would consider.
Can someone give me some advice, tutorials and useful links regarding my following question.
This system I want to write must be dynamic e.g. the model may change allot and should not be hard coded in C#.
For example if I had a JSON document saved holding ID, NAME, FULL NAME and then added a property called PHONENUMBER I would not want to rebuild the C# code or redeploy.
Is it possible to build C# models from a dynamic JSON? and then be able to manipulate it?
If so what library are most recommend for this type of system? What libraries work best with .NET?
This question is a step in to starting my university project.
Thanks for help & advice.
Yes, you can do that quite easily with RavenDB.
You can do it in one of two ways.
Either you will use a fully dynamic model, utilizing the C# dynamic keyword. That will let you do pretty much whatever you want, including adding properties at runtime, querying on runtime properties, etc.
However, a more common setup is that you'll use a lot of common properties (a customer has to have a name, for example). So you'll have a model that looks something like this:
public class Customer
{
public string Id {get;set;}
public string Name {get;set;}
public dynamic Props {get;set;}
}
The fixed properties are coded in C#, which helps you get into an easier, more consistent model and work with all the usual compiled tooling.
The dynamic stuff is in the Props property (which is usually initialized to ExpandoObject).
Note that you cannot do linq queries using dynamic. This is a limitation of C#, not RavenDB. You can still query dynamically using RavenDB, but you'll have to use the string based query API.
I implemented a Json.NET serializer wrapper that may help you:
https://github.com/welegan/RedisSessionProvider/blob/master/RedisSessionProvider/Serialization/RedisJSONSerializer.cs
I use it in my library which stores the contents of ASP.NET's Session object inside of Redis, which is a NoSQL option you did not mention. Still, given the typeless nature of Json, I imagine it will be applicable to your needs regardless of what NoSQL db you choose. The basic steps are:
Serialize:
Decide on a delimiter (I probably could have chosen a better one)
Store the type info (you can cache it for performance gains)
Store the object data after a delimiter
Deserialize:
Find the type info up to the delimiter
Deserialize the Type object
Pass Type as well as the object data to the library of your choosing. At the very least, Json.NET and ServiceStack.Json both expose serializers that will do the trick.
Edit
Seems I misunderstood part of your question. You want to be able to support adding json properties without redeploying your C#, and my example would strip out the extra properties during the serialize step back to the noSql db. You can use either a Dictionary<string, string> or ExpandoObject like ayende or mxmissile suggest, but keep in mind you will then have very few guarantees about the type of the properties of the object you get out.
In other words, you can freely add property names but as soon as you change the type of a property from int to long your code will break unexpectedly. Depending on your use case, that may or may not matter, just something to keep in mind.
Yes, using a Dictionary. However, I am not sure how those database systems handle dictionaries. Gracefully or not.
No, c# is compiled, so once that is done, there is no changing it without changing the source and compiling again. I think you should add some Javascript for that as it is a JS strong point.
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.
First I will give a little background info so this question isn't completely without context:
I am writing a program which needs to read in binary files of which I know the format/layout. The bulk of these files contain "structs", with the layout of each stored in the header of the file. Each struct contains fields which could be either structs or "base" types (which are not structs, and can be either value or reference types like float or String or Vector3).
I do not need to access most of the data in these files, so I would not have to define all possible structs for my current project, but there are enough that I would have to define that doing it manually would be tedious and time consuming.
My problem is that there are an extremely large number of these structs (2500+ different ones, though only the ones appearing in a file are defined in that file's header). I would like to be able to read them in, without having to manually define each one, in a way that makes all the data available in the same way. My current thinking is that I should create a class like this:
class Struct{
StructDefinition _def;
List < Field > _fields;
...
}
In the field class I would need to be able to store both structs AND base types (or more importantly reference and value types). Is there a way to do this without turning everything into an object then casting it to the correct type when I need it? Also, is this the best way to go about reading in these files, or is there a better method?
dynamic (.NET 4.0) can do this at runtime, but you lose compile-time type safety and IntelliSense.
For your particular situation, I would recommend the new file mapping classes in .NET 4.0.
If you need a pre-.NET 4.0 solution, consider looking at the file as a series of offsets instead of structures, and use a FileStream, seeking to and reading in only the information you need. This is kind of like a poor-man's file mapping. Note that in this situation, it's more performant if you only move forward through the file.
Using either of these last two solutions, you don't have to waste time and memory reading in data you won't need anyway.
If you define an interface that contains all of the methods that you need to manipulate the fields, then you can create a small set of objects - one for reference and one for value types.
As long as each of these objects implement the same interface, you will be able to work with them generically.