I store a whole bunch of files as embedded resources within an assembly. Calling Assembly.GetManifestResourceNames returns things similar to the following:
Folder1.Resource1.cshtml
Folder1.Folder2.common.js
etc.
I have a class that builds a virtual directory/file system based on these names. However, I am having an issue with resources such as:
Folder1.Folder2.jQuery-ui-1.10.3.custom.min.js
As there is no way (unless you handle it as a special case) to know that jquery-ui-1 and 10 and 3, etc are not folder names, with a final resource of min.js. Currently I get around this by ensuring that all my embedded resources do not contain multiple periods. That said, is there a way to change the path separator to a different character to avoid this problem entirely?
Are you able to get the ResourceManager? If so, you can use BaseName
You could use the Assembly.GetTypes() to use the type to get to the ResourceManager, or you could even potentially cross reference directly against the FullName of the Types.
Related
I'm trying to figure out how to choose between two different (identically designed) Resources files in code. All of the examples I can find online are in reference to having different language specific Resource files which are chosen based on setting the culture value. That won't work for my probelm.
This is a web service which returns an image from one of several different image repository systems. Depending on a parameter passed in to the method, the service will need to access an image repository system in order to pull the image being requested. When accessing the image repository, there are a bunch of "magic string" GUID values that represent different IDs for various lookups in that system. One of the purposes of this service is to hide all of that complexity from the user. Rather than hard-code these GUIDs into the code, I have put them into a Resources file.
The problem is this: Each different image repository system has the same set of magic string IDs that need to be used. However, the actual GUID values for these magic strings are different depending on which repository you are connecting to. For example, there is a value called "GroupIDPrompt" which might be "8a48f393642a753f0164418b670a7cdf" on one system, but "63aa28c3637b58680163b25f7e5a5d96" on a different system. In code, I'd like to refer to this value as just "Resources.GroupIDPrompt" or something similar, but I need to be able to set which Resources file will be used at runtime, based on what the consumer of the service sent me.
Normally, I might solve a problem like this by using an interface, and instantiating a specific implementation of that interface based on the request. There are two reasons that doesn't work here - #1, Resource code files are generated automatically, and if I edit them to make them inherit from an interface, this will get broken everytime the file is regenerated. #2, All resource values are created to be static members, and interfaces aren't allowed to declare static members.
I could throw the Resources files away and instead build a class to expose these values, but that means re-introducing magic hard-coded strings to my code. That isn't too terrible, I suppose, but the Resource editor is really quite handy for managing and editing these values.
I am trying to figure out whether a global string resource file for the entire application or a local resource file for each small sub area would be a better choice.
It seems like a translator would appreciate the one file approach vs hundreds of them. It is also easier to write helper functions since there is only going to be one static resource class.
The downside is that the resource name might be really long to properly identify the place where it is suppose to be in and it might be hard to locate related strings when the file grows big.
Where as a local resource file would produce lots of duplicated strings or make it confusing if we need to use multiple instances of static resource classes because the strings are spread between multiple of them.
So what would be a better way to go?
Maybe you could break your resources into 3 files (depending on your application design):
ResourcesCore
For translated enum values and common expressions
ResourcesEntity
For strings related to translation of some entity properties (e.g. Person.Name)
ResourcesWeb (or ResourceUI)
For other UI related stuff (like strings on UI, labels, descriptions, etc.)
You could then use ResXManager extension for VS to manage you resource strings (way easier than native .NET ResX manager, at least for me).
I work on a product where we have to worry a bit about localization. Currently, this is the workflow for when I have to use(or add) a localized string:
Search resources.resx file(which has hundreds of items)
If found, then copy the name. Otherwise, add a new string and copy the name
Then, use ResourceFactory.ResourceMgr.GetString("MY_MAGIC_STRING") (where ResourceMgr is just a static field to a ResourceManager)
This 3 step process for any strings is a real pain. Are there any patterns or ways to make this process easier?
Auto-generated files with access to each individual string are much easier to use - set "Custom tool" for RESX file to PublicResXFileCodeGenerator.
Code would look like:
using MyProject.Resources;
...
localizedText = Resources.SomeReasonableName;
Side notes:
having multiple RESX files along with auto-generated IDs have additional benefit of intellisense giving you reasonable number of choices.
depending on how translation is handled you may be better not worrying about duplicated text in RESX file (except maybe OK/cancel kind of strings). It may be easier to deal with duplicated strings at translation time.
There is this Java solution that might give you some ideas:
http://rodionmoiseev.github.com/c10n/
The idea is to store translations in the source code itself, using annotations on interface methods. Then, by using a special utility, you can dynamically create proxies (classes dynamically implementing the interface) that would return localised string value when invoking the interface method.
This way, "MY_MAGIC_STRING" is replaced with a call to MyMagicString() method, which gives you some spelling/type safety and makes it more refactoring friendly.
Where is the best place to put string literals within the class? Should they be declared as constant members, should they be referenced in the method (provided the string literal is only ever used once), should they be put in a helper class or elsewhere?
Are you referring to strings that are displayed to user and require internationalization?
In .NET and Java you can use Resource Files that lets you use a key/value resource file. This has the added advantage of not needing compilation every time you need to change text, and you don't need to be a coder to be able to modify the resource files.
If you're just talking about internal strings that are used (like keys, IDs etc.) then I wouldn't fuss too much about it - some people like "constants.cs", while other like it within the file that is using them, and others like putting each set of constants in their own relevant packages. Just keep it ... Constant.
I'm currently working with some code involving saving a file to a user-defined file. If the user passes in a filename with no extension, the code autodetects the extension based on the file type (stored internally).
However, I'm having a hard time determining whether the filename passed to the code has an extension or not. I'm using Path.HasExtension(filename) and Path.GetExtension(filename) but it seems to be exhibiting strange behavior:
File.EXT => .EXT is the extension. This is fine.
This Is A File.EXT => .EXT is the extension. This is also fine.
This Is A File. Not An Extension => . Not An Extension is the extension. However, I would think of this as a file without an extension. Windows thinks so too when I create a file with this name (creating a file with an unrecognized extension causes windows to call it a EXTENSIONNAME File, whereas files without an extension such as this one are just called File).
This Is A File.Not An Extension => .Not An Extension is the extension. Same problem as above.
Also note that this same behavior is evident in Path.GetFileNameWithoutExtension(filename) (e.g. it reports the filename without extension on the last two examples to be just This Is A File).
So what I'm taking from this is that .NET and Windows differ on what they think of as an extension.
The Question:
I'm wondering if it's OK for me to implement code such as this:
if(!Path.HasExtension(filename) || Path.GetExtension(filename).Contains(" ")) {...}
since that would pull my code's definition of a proper extension more in line with how Windows treats things. Or is there something I'm missing here which explicitly says I must allow spaces in my extensions?
I've searched and found this slightly similar question, but the documents linked therein only specify that it's not recommended to end the extension with a space/period -- they say nothing about spaces within the extension.
The extension on a filename in Windows is purely a convention. The GetExtension and HasExtension methods only look for a dot in the filename and act accordingly. You are free to put spaces anywhere you like within the filename (including the extension).
When you say "Windows thinks so too", it's really just some code in Explorer that tries to parse out extensions, and it simply uses a slightly different algorithm than .NET.
How the filesystem handles names and how the Windows shell (i.e. Explorer) handles file names are two completely different beasts.
The filesystem doesn't care about spaces, dots or anything else -- to it, the filename is just one opaque string (with some restrictions on allowed characters). The name/extension separation is just a made-up convention. The shell, on the other hand, is free to make up its own interpretation of what an extension is because its purpose is not to store and retrieve file information but rather to provide the user with a better experience. So don't go looking there for answers.
I would suggest going with what the System.IO methods return (because following the convention is good), but you can do whatever you like in your code if there's a good reason for it.
There is no official definition of what an extension is. The common convention is that everything after the final . is the extension.
However if you would grab a HUGE list of all common-used extensions I think you'll only find a handful of examples where spaces in an extension are used.
I would say, disallow spaces in extensions. 999/1000 times the user didn't mean it as an extension.
To quote Wikipedia on filenames:
. (DOT): allowed but the last occurrence will be interpreted to be the extension separator in VMS, MS-DOS and Windows. In other OSes, usually considered as part of the filename, and more than one full stop may be allowed.