Ralf
Ralf

Reputation: 313

Change CodeGenerator for resource file in Visual Studio C#

In my VS2015 project I'm using resource files for keeping track of my texts and corresponding translations. The texts are kept in resx files and for the main resx file a corresponding .designer.cs file is created automatically which exposes the texts through properties.

My problem now is that I have to modify the generated code in the .desginer.cs for some additional functionality. Of course this only makes sense when I modify the template that VS uses to generate the code - but how can I do that?

I noticed that I'm allowed to specify a 'Custom Tool' for my main resx file which is currently set to 'PublicResXFileCodeGenerator':

I did some research on the automatic code generation but could not find a basic tutorial for it but only some complicated examples that go back to VS2008. Unfortunately I still do not know where this 'PublicResXFileCodeGenerator' comes from so that I could use it as a base for my own approach to start from. I also do not know if my own template would then be a .rgt file and where I would have to put it (I saw those rgt files in one example but could not find out where they were assigned/used).

Could anyone please recommend me a way to modify the automatic code generation of my .Designer.cs?

Thanks!

Upvotes: 4

Views: 4142

Answers (2)

dukedukes
dukedukes

Reputation: 266

The way I did this was deleting the custom tool property for, say, the MyResource.resx file so it no longer generates anything, then creating a T4 template that generates the MyResource.Designer.cs class instead.

So your solution structure would look something like:

enter image description here

you can base the structure off of the regularly generated designer file, or just go your own way with it.

You will need to load the resource file in some way. Here is an example using ResXResourceReader (unfortunately this is in the System.Windows.Forms assembly) and having hostspecific set to true in the T4 template header so you can access files on a relative path:

string fileName = this.Host.ResolvePath("MyResource.resx");
ResXResourceReader reader = new ResXResourceReader(fileName);

// This lets you access the comment. If set to false the DictionaryEntry's
// value will simply be the resource value.
reader.UseResXDataNodes = true;

foreach (DictionaryEntry resource in reader)
{
    ResXDataNode node = (ResXDataNode)resource.Value;

    string key = (string)resource.Key;
    string value = (string)node.GetValue((ITypeResolutionService)null);
    string comment = node.Comment;
}

As an alternative you can choose to still generate the regular MyResource.Designer.cs and enumerate the resource set (taken from this answer):

ResourceSet resourceSet = MyResource.ResourceManager
    .GetResourceSet(CultureInfo.CurrentUICulture, true, true);
foreach (DictionaryEntry entry in resourceSet)
{
    string resourceKey = entry.Key.ToString();
    object resource = entry.Value;
}

My code regenerates on build and when saving the template which was enough for me. It builds by using a variation of this answer. Note that the batch file does run TextTransform.exe to generate the T4's and finds this exe in a partially hard-coded path based on visual studio version, but you can figure out the version in the batch file if you like.

Not a perfect solution but may be an alternative to running external custom executables to generate your code. This at least doesn't require any extra pre-requisites for anyone's development environment.

Upvotes: 1

Ralf
Ralf

Reputation: 313

After doing a little more reseach I stumpled upon this MSDN article which explains how a "Custom Tool" or "Single-File generator" can be implemented. One part of this is that the generator needs to be registered as a COM component which does not sound very appealing to me (Would I have to register this on every team mate's computer to make it run on their system, too?).

As an alternative I decided to create a simple console application which takes 'SourceFile', 'DestinationFile' and 'NameSpace' as parameters. This small application will then be able to generate the .designer.cs for me.

Adding the tool to TFS and calling it from the 'Pre-Build event command line' of my resource project should be piece of cake.

Checking out the .designer.cs from TFS (or adding it) shoudl not be a big deal (so I was told).

Iterating through the RESX file is convenient when using the System.Resources.ResXResourceReader.

In the end this is not a very nice workaround, but I'd still prefer it over the other solutions that I found so far :-/

Upvotes: 1

Related Questions