Best way to manage resources(Not necessarily RESX files) in .Net solution - c#

This sounded like a trivial question initially but I did not come across any solid/best practice solution on how to do this so I am asking the question here. Now, let's imagine that we have to work with couple of ".txt" files in our code which is in a class library.
Now, I think there are 3 major ways to handle this:
Just put everything in your Bin/Debug/Resources folder of the calling application and in your code use "Resources\*.txt". I think this is the simplest and most unobtrusive way to handle this. However, there are many trivial problems with it:
When you check in the source control would not check-in the files inside the Bin/Debug folder
So in this case, probably adding the folder one level above and then writting post-build scripts is the most efficient option I guess?
Add resources folder on the same level as Bin folder. That way we can successfully manage it using the source control. however now when we need to reference it through our code it becomes tricky
We can reference this files assuming that the Binary folder's structure is like Bin/Debug and reference to the Resources folder like ..\..\Resources
But this structure is not always guaranteed what if the binary folder structure is like Bin/ (without any debug folder in it) then ../../Resources is going to fail
Add all the txt files as .RESX files. But I am not sure if it is the practice around everywhere and the most popular way to store resources.
-Also, the code that we have to write to access the resources files sounds like cumbersome as oppose to just picking up the file from windows file system.
Probably I am missing something trivial but I was just curious and was thinking that it should be much more simpler than this. Any suggestions?

Create a different project in the solution called Myproject.Resources.
Next install Microsoft MAT and manage your translations with MAT: https://developer.microsoft.com/en-us/windows/develop/multilingual-app-toolkit
You manage your translations with MAT and the .resx files are kept up-to-date. ;-)

Related

c# Storing resources(specifically images) in folder structure

If I want to add pictures, I have to put those into the resources and access them from the picturebox.Image property by using this:
AddPicturesFromOtherFolders.Properties.Resources.myPicture
Thats the only way I know. That works fine if I have 10 or so images, but what if I had 500 images? Nobody could keep track of anything. So I would like to structure these hyperthetical 500 Images in a folder structure which I could then access with something like:
pictureBox1.Image= ../../Assets/img/specialImages/myImage.png
That would be very neat, but I have found no way, that involves 100% C# code.
I would be wuite grateful, if you could help me.
Have a nice day,
Alexander Lenssen
You could use Image.FromFile and load the image from any file you have stored in your file system. For example:
pictureBox1.Image.FromFile(#"D:/Assets/img/specialImages/myImage.png");
There is no way that involves 100% C# code. At least some Compiler options or Setup actions are nessesary. But the first question is even where to store it: Programm Directory or UserProfiles?
Asuming these images are static (will only change when a installer runs), you can just store them into the Programm Directory. And from there deploy them with the rest of the code. Getting them Into the Output directory is not that difficulty. Visual Studio has options for that: https://msdn.microsoft.com/en-us/library/0c6xyb66.aspx You could go further, like having a Shared Repository for Images (i.e., most Photoshop programms have one Content Folder under Programms).
You can go as far as "soft linking" them, wich means you can have one actuall folder on your disk that will be copied/synched into the output directories on any buil.
If you need to Update those Images them on the fly (without adminsitrative rights), stuff becomes more complicated. You can still do it via the SpecialFolders. CommonApplicationData seems like the right place to put this kind of stuff. Even Steam and Minecraft's old Java Launcher do quite some storage there. Not to mention every WebBrowser.

Read SQL query file from project directory

I've put 3 especially large SQL queries within my Visual Studio project, under a folder "Queries" that is in the project directory (not the solution). Is there an eloquent way to access these files? I was hoping that something like #"Queries/firstSqlQuery.sql would work.
Specifying the full path, like with #"C:\\Users\John\Documents\VisualStudio2010\Projects\MySolution\MyProject\Queries\firstSqlQuery.sql
is something I'd really rather not do, since it requires me to go back into code and fix the path, should the application move.
EDIT: For some reason, the page is looking for the files in C:\\Program Files(x86)\Common Files\Microsoft Shared\DevServer\Queries\firstSqlQuery.sql. Why is it looking in this location, when the executable directory is different?
You can do something like this... if it's outside of project. (When I intitially read this-- I misread and thought it was in the solution directory which I was assuming contained the project)--
var pathToBin = Assembly.GetExecutingAssembly().Location;
var directoryInfoOfBin = new DirectoryInfo(pathToBin);
var solutionDirectory = directory.Parent().Parent();
var pathToSolution = solutionDirectory.FullName;
but this is much simpler if it's in the project
System.Web.HttpContext.Current.Server.MapPath("~/Queries/firstSqlQuery");
There are a number of ways to handle this, but there is a fundamental understanding you must gather first. Issuing something like #"Queries/..." isn't, by itself, isn't going to do anything. You need to leverage the System.IO namespace to perform IO operations.
With that part of the foundation, let's lay some more, when you issue a command like this:
File.ReadAllText("firstSqlQuery.sql");
the path that is implied is the Working Directory of the assembly that's executing the code. When debugging an application in Visual Studio, especially and ASP.NET Application, that's the bin directory that resides under the project directory, by default. So, if you did want to access the Queries folder, you would have to do something like this:
File.ReadAllText(#"..\Queries\firstSqlQuery.sql");
so, that's one way of handling it.
Another way of handling it would be to copy the file over into the bin folder every time the project is built by looking at the file properties (e.g. create a Post Build Event), but that's more work than I think you're looking for.
Again, the key here is to understand what directory you're starting in.
Finally, one thing worth noting, if you leverage the directory structure you'll need to ensure that the Queries folder gets deployed to the live site. That probably goes without saying, but I've seen people run into that exact problem before.
You could make sure your query files are copy to the output directory when you do a build and read the files from there without having to set a path.

Using zip archives

I created quite a neat application for backups. It just copies the directories you specify to wherever you want. Unfortunately I encountered a problem. The maximum length of the file path is about 250 so what happens is that the program can't copy files if the new location path is longer - and the program collapses.
I learned that using zip archives would resolve the problem. But... The program uses some filters and it's logic isn't that straightforward. I really wouldn't like to rewrite it all.
My program visits all subdirectories in a specified directory and checks if there are any new or modified files there. If it finds some it copies it to ..../Backups/......../dir_A/dir_B/file. Every file and dir is processed separately (it's checked if it was modified, if it fits the filters, etc)
What I need is something that would help me substitute Backups directory with Backups.zip Especially offering something like this:
myArchive.copyFile("dir_a/dir_b/...../file", original_file_path);
myArchive.fileModificationDate("dir_a/dir_b/...../file");
myArchive.getDirectotiesIn("dir_a/dir_b/");
Is there such a feature in .Net? Or maybe there is a free library for this?
There are mainly two free alternatives for handling zip files in c# :
DotNetZip
SharpZipLib
I prefer DotNetZip.
SharpZipLib

Use external file or resource?

I am writing a C# application that uses a long "hard-coded" string.
For maintainability reasons I have decided to put this string in an external text file and load it. Is this a good idea? The extra I/O does not seem big in this case.
I realize that I also have an option to embed this file as a .resx resource. Is this a better idea? The file will never need to be localized.
If you intend to allow users/administrators to change the string, I agree with the other answers, and I'd suggest putting it in settings.
If you don't want it to be editable after deployment and it will only be modified by you and your developers, then I would put it in an embedded resource (note, this is not the same as a .resx file). You would read it at runtime like this:
Assembly assembly = Assembly.GetExecutingAssembly();
Stream stream = assembly.GetManifestResourceStream(“MyAssemblyNamespace.MyTextFile.txt”);
StreamReader reader = new StreamReader(stream);
string theText = streamReader.ReadToEnd();
Update: This is solution that is easy to maintain. The .txt file will just be another file in your solution explorer in Visual Studio and you can edit it just like any other file, keep it under source control like any other file, etc. To turn it into an embedded resource by changing the Build Action in the properties window to "Embedded Resource".
The end result is that your file(s) get embedded in your DLL so that you only have 1 DLL to distribute instead of a DLL and a folder of files that have to move around together.
Update 2: Regarding "production debugging", this is a very static solution, and so you won't be able to change the contents of the text file at runtime because the file is baked into the DLL at compile time. For reading the contents of the file, you can use tools like reflector to view the embedded resources of a DLL. You could also write a simple command line tool that dumps all the embedded .txt files from a DLL into individual files for you to look at.
For memory usage, there isn't a solution more efficient than "I load it from a file into memory only exactly when it is needed". You have to decide whether the improved maintainability and deployment is worth the cost of a little extra memory when your DLL is loaded into memory for your specific situation. That said, you haven't said how large these files are. If they are really huge (megabytes+), I would probably not use this solution and would go with loose files on the hard drive. If they are generally pretty small (hundreds of kilobytes), I wouldn't worry about the extra memory unless you are in some kind of embedded device situation where RAM is really tight.
Why not make it an appSetting in your web/app.config file?
<appSettings>
<add key="MyLongString" value="This is a really long string value that I don't want hardcoded" />
</appSettings>
Then, in code:
using System.Configuration; //To ease your typing pains
var myReallyLongString = ConfigurationManager.AppSettings["MyLongString"];
I would suggest to use Application Settings.
You can follow this MSDN link how to use Application and User Settings.
I would put this in an application configuration file.
Even better would be to add a Settings file to your project. You can then easily add configuration settings through Visual Studio.
See this link.
You could then access your string by using the following:
Settings.Default.MyString;
In addition, settings are strongly typed, so you don't need to do any conversions when you retrieve them.
To more directly answer your question, the "best practice" would be to use a resource file for any localizable (even if you're not going to localize it) string in your application. This allows you compile-time access to the string and keeps it from being externalized as a separate file to deploy with your application.
I suggest using this approach; settings are similar, but should not be used unless what you're storing there actually represents a setting. Constants are the other option, but in the case of a long string, I'd stay away from them, just for the sake of maintainability.

how to get stronly typed local resource file?

i really love the idea of it as i can create a folder for my user control, and make sub folder images, css, and put local resource file, so the whole thing is contained in one folder, and that makes it really efficient for me (management wise).
but the bugger is you cant get intellisence like global resource, so is it possible in any way ?
AFAIK: ASP.NET and Visual Studio in their standard configuration can only do this for global resources.

Categories