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.
Related
I have a solution with several self-contained classes and methods. For example, I have:
a FileDownloader class that has multiple different methods that download files based on passing in a URL or multiple URLs
a DataTransformations class that has multiple methods that transform data depending on what is necessary for a given operation
a FileWriter class that writes some data to some kind of file type or file format
etc.
I have all of these classes as .cs files under the same solution. I can consider the order of executions for some specific operation and call the methods from MAIN in the correct order and it produces the output that I expect. I will eventually, however, need to call some or all of these methods in many different configurations for several different processes and I don't know how to do that. I know how to pass in configuration through command line arguments, but even that requires the specific order and number of methods called stays the same between processes. This is not tenable because I will not need to download files in some instances and I will not need to transform data in some instances etc. I am very new to .NET development and I have not yet wrapped my head around how to truly decouple these classes from each other. Do I have to deploy a different solution for each class? I would like to just be able to say "call file downloader with these parameters" and then "perform data transformations based on these parameters" basically like steps in an execution job.
Dirty Answer, Compile as a library and then add a reference in whatever project you want to use those methods for. you can then call the methods by name (LibraryName).MethodName(Parameters). of course you will need to always have that DLL in whatever other project need access. if you have any questions on how to do this let me know.
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 am building a multi-language MVC application and have a series of resource files with translated strings for messages that will be displayed to the user.
Is there any way of ensuring that any resource files added in the future have all required keys and are spelled correctly?
As an analogy, if the resource file was a regular class, you could provide an interface to ensure that all required method and properties were present in the implementing class. Is there a similar concept for resource files?
I've been unable to find a supported way to enforce an explicit contract upon a .resx file. Since your goal is ultimately to catch implementation errors before they show up at runtime (and compile time checking isn't possible), I recommend falling back to static code analysis. Luckily, .NET makes this trivially easy:
Use the System.Resources.ResXResourceReader class to read the contents of the resx files to be validated.
Implement a test that asserts against all required keys in the "contract" you'd like to enforce on the resx.
Test should run as part of an existing test suite, and failure will warn a developer of the implicit contract before encountering the problem at runtime.
Since your resource files will exist in a known location, you can trivially ensure that the tests run against all resx files in that directory. In this way, you don't even need to update the test when new resource files are added, only if the contract changes.
I've used a similar approach to help with maintenance of stored procedure names kept in (an extensive number of) resx files. Since the resource files are spread across dozens of projects, manual maintenance is tedious and error-prone -- in other words, it doesn't get done. The static code analysis approach has yielded few downsides, and I think it would work well in your case as well.
Landing page for resource files on MSDN
ResXResourceReader on MSDN
System.Resources.ResXResourceReader requires a reference to System.Windows.Forms. It's available on both .NET and Mono.
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.
I have a C# WinForms application in Visual Studio 2010 that is used by two different customers. The basic functionality of the application is the same for each customer, but certain lines of code (names of stored procedures, resources, certain behaviors) are different between versions. So far, I have kept the application in the same project, and used preprocessor directives when building/publishing to switch between which deployment to use. However, the scope of the project has grown to a point where this is no longer feasible.
Since so much of the code is shared, I'm trying to avoid duplicating source code files. I'm wondering what the best approach is to maintaining an application that requires different versions to be deployed simultaneously.
Use interfaces to define your classes. Having an interface means that you can have multiple implementations of the same interface, one for each of the clients. This will require you to analyze your existing codebase and identify logical separations in your code where these interfaces can be defined.
You then have the ability to load an interface as needed based on the client. You could, for example, do this via configuration. Based on a configuration value you load Implementation1 or Implementation2. There are many, many ways to accomplish this particular bit. You should read up on dependency injection, inversion of control and have a look at tools like Ninject, Autofac, Unity.
It may actually be difficult at first considering how you have been using preprocessor directives but seeing as how your application is growing, you will need this refactoring to happen. Keep in mind that if you do not do it now, this refactoring will be a lot more expensive later as your application becomes more complex.
The different functionality should be a part of the application's architecture. If you need different functionality for different customers, abstract it away - create an interface that wraps up the behaviour, then implement it in two different ways in two different assemblies. Then (depending on your deployment mechanism), you can ship your app with either one DLL or the other. To avoid having to recompile, add references, etc, you can use Dependency Injection frameworks such as Ninject, Castle Windsor, MEF etc. That's a "plugin-like" architecture, if code is sufficiently different.
If you're talking about text, colours, basic differences, they should simply not be hard coded but instead data-driven. If your app is internet-connected, it could download the appropriate settings when the user logs in. Else, something to indicate the text/colours/behaviour could be put in a config file specific to the customer. You can use config transforms to simplify that process.
You might be able to separate some of the differences by using resource, configuration, or property files of some kind. By this, I mean you store some kind of value in the file, such as the name of the stored procedure to use in a particular situation. Then your code reads the name from the file and runs it. You can change the values in the file without needing to rebuild your code for each deployment.