The missing ResWFileCodeGenerator custom tool for Visual Studio 2012
I’ve been doing quite a lot of Windows Store Apps on Windows 8 lately. Ever since I started I always seemed to miss the ResXFileCodeGenerator custom tool. This is because in WinRT when you want to load a localized string in code then you will have to do something like this:
var resources = new ResourceLoader();
var localizedString = resources.GetString("SomeResourceName");
This of course can easily lead to a lot of errors. In my case I got a little to eager while refactoring and forgot to notice that I was also changing hard coded strings. This broke the code quite a lot. Because of this frustration I decided to implement my own custom tool since Microsoft didn’t provide one
The project is open source and is available at Github. Here’s a preview of the description which I took directly from my CodePlex project site.
Download from Visual Studio Marketplace
Features
- Define custom namespace for the generated file
- Auto-updating of generated code file when changes are made to the .ResW Resource file
- XML documentation style comments like “Localized resource similar to ‘[the value]’”
- Supports Visual Studio 2015, 2017, 2019, and 2022
- Supports dotted keys - Replaces . with _ (e.g.
Something.Awesome
=Something_Awesome
)
Custom Tools
- ReswFileCodeGenerator - Generates a public class
- InternalReswFileCodeGenerator - Generates an internal (C#) / friend (VB) class
Supported Languages
- C#
- Visual Basic
Screenshots
C# Usage
string test1, test2, test3;
void LoadLocalizedStrings()
{
test1 = App1.LocalizedResources.Resources.Test1;
test2 = App1.LocalizedResources.Resources.Test2;
test3 = App1.LocalizedResources.Resources.Test3;
test4 = App1.LocalizedResources.Resources.Test_With_Dotted_Keys;
}
Visual Basic Usage
Dim test1, test2, test3
Private Sub LoadLocalizedStrings()
test1 = AppVb.LocalizedStrings.Resources.Test1
test2 = AppVb.LocalizedStrings.Resources.Test2
test3 = AppVb.LocalizedStrings.Resources.Test3
test4 = AppVb.LocalizedStrings.Resources.Test_With_Dotted_Keys;
End Sub
Generated C# Code
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------
// <auto-generatedInfo>
// This code was generated by ResW File Code Generator (http://bit.ly/reswcodegen)
// ResW File Code Generator was written by Christian Resma Helle
// and is under GNU General Public License version 2 (GPLv2)
//
// This code contains a helper class exposing property representations
// of the string resources defined in the specified .ResW file
//
// Generated: 05/20/2019 15:47:37
// </auto-generatedInfo>
// --------------------------------------------------------------------------------------------------
namespace App2
{
using Windows.ApplicationModel.Resources;
public sealed partial class Resources
{
private static ResourceLoader resourceLoader;
/// <summary>
/// Get or set ResourceLoader implementation
/// </summary>
public static ResourceLoader Resource
{
get
{
if ((resourceLoader == null))
{
Resources.Initialize();
}
return resourceLoader;
}
set
{
resourceLoader = value;
}
}
/// <summary>
/// Localized resource similar to "test"
/// </summary>
public static string Test
{
get
{
return Resource.GetString("Test");
}
}
/// <summary>
/// Localized resource similar to "test"
/// </summary>
public static string Test2
{
get
{
return Resource.GetString("Test2");
}
}
/// <summary>
/// Localized resource similar to "test"
/// </summary>
public static string Test3
{
get
{
return Resource.GetString("Test3");
}
}
/// <summary>
/// Localized resource similar to "test"
/// </summary>
public static string Test_With_Dotted_Keys
{
get
{
return Resource.GetString("Test/With/Dotted/Keys");
}
}
public static void Initialize()
{
string executingAssemblyName;
executingAssemblyName = Windows.UI.Xaml.Application.Current.GetType().AssemblyQualifiedName;
string[] executingAssemblySplit;
executingAssemblySplit = executingAssemblyName.Split(',');
executingAssemblyName = executingAssemblySplit[1];
string currentAssemblyName;
currentAssemblyName = typeof(Resources).AssemblyQualifiedName;
string[] currentAssemblySplit;
currentAssemblySplit = currentAssemblyName.Split(',');
currentAssemblyName = currentAssemblySplit[1];
if (executingAssemblyName.Equals(currentAssemblyName))
{
resourceLoader = ResourceLoader.GetForCurrentView("Resources");
}
else
{
resourceLoader = ResourceLoader.GetForCurrentView(currentAssemblyName + "/Resources");
}
}
}
}
Generated Visual Basic Code
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.42000
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict Off
Option Explicit On
Imports Windows.ApplicationModel.Resources
'--------------------------------------------------------------------------------------------------
'<auto-generatedInfo>
' This code was generated by ResW File Code Generator (http://bit.ly/reswcodegen)
' ResW File Code Generator was written by Christian Resma Helle
' and is under GNU General Public License version 2 (GPLv2)
'
' This code contains a helper class exposing property representations
' of the string resources defined in the specified .ResW file
'
' Generated: 05/20/2019 15:48:18
'</auto-generatedInfo>
'--------------------------------------------------------------------------------------------------
Partial Public NotInheritable Class Resources
Private Shared resourceLoader As ResourceLoader
'''<summary>
'''Get or set ResourceLoader implementation
'''</summary>
Public Shared Property Resource() As ResourceLoader
Get
If (resourceLoader Is Nothing) Then
Resources.Initialize
End If
Return resourceLoader
End Get
Set
resourceLoader = value
End Set
End Property
'''<summary>
'''Localized resource similar to "test"
'''</summary>
Public Shared ReadOnly Property Test() As String
Get
Return Resource.GetString("Test")
End Get
End Property
'''<summary>
'''Localized resource similar to "test"
'''</summary>
Public Shared ReadOnly Property Test2() As String
Get
Return Resource.GetString("Test2")
End Get
End Property
'''<summary>
'''Localized resource similar to "test"
'''</summary>
Public Shared ReadOnly Property Test3() As String
Get
Return Resource.GetString("Test3")
End Get
End Property
'''<summary>
'''Localized resource similar to "test"
'''</summary>
Public Shared ReadOnly Property Test_With_Dotted_Keys() As String
Get
Return Resource.GetString("Test/With/Dotted/Keys")
End Get
End Property
Public Shared Sub Initialize()
Dim executingAssemblyName As String
executingAssemblyName = Windows.UI.Xaml.Application.Current.GetType().AssemblyQualifiedName
Dim executingAssemblySplit() As String
executingAssemblySplit = executingAssemblyName.Split(Global.Microsoft.VisualBasic.ChrW(44))
executingAssemblyName = executingAssemblySplit(1)
Dim currentAssemblyName As String
currentAssemblyName = GetType(Resources).AssemblyQualifiedName
Dim currentAssemblySplit() As String
currentAssemblySplit = currentAssemblyName.Split(Global.Microsoft.VisualBasic.ChrW(44))
currentAssemblyName = currentAssemblySplit(1)
If executingAssemblyName.Equals(currentAssemblyName) Then
resourceLoader = ResourceLoader.GetForCurrentView("Resources")
Else
resourceLoader = ResourceLoader.GetForCurrentView(currentAssemblyName + "/Resources")
End If
End Sub
End Class
Parenthood
Once again I have taken a break from blogging. Parenting and my new family has been my absolute top priority and I’ve been having a hard time finding the time to write articles. I really enjoy spending time with my son and wife and I take advantage of every possible moment to do so.
I ended up at a schedule that starts around 5:30 AM in which my son wakes up, and wakes me up. I go and start preparing some breakfast for him. We then have a cozy morning playing around the house. I drop him off at day care as late possible (in my case 9:00 AM) and then drive to the office, or to a customer, or back home if I’m working from home. I pick my son up at between 3:00-4:00 PM and spend time with him and my wife until around 6:30 PM (this is his bed time and I’m very lucky that he has no trouble sleeping). From around 6:30 to 8:00-9:00 PM I spend some time with my wife discussing how our days went and do some planning for the following days. My wife goes to bed a bit early, and when that happens I go back to work. Since I drastically shortened by day, I need to do quite a bit of catching up at night. I usually work an extra 2-3 hours more at night, then I have an hour or 2 to give my mind a rest or work on a hobby project. My day usually ends between 12:30 AM and 2:00 AM. I need at least 4 hours of sleep to recharge for the next day, otherwise I won’t be able to last a full week on my schedule.
Hence the break from blogging :)
Windows Phone and HTML5 - Danish Developer Conference 2012 Session Recording
Here’s the recording of my session on Windows Phone and HTML5 for the Danish Developer Conference 2012, for those who missed it…
You can also watch it on YouTube