Create code-behind files for resource.resx
As I saw in the next generation of Visual Studio .NET there is a code-behind file for resource files. I tought this is an idea to create a small macro doing the same job.
You can copy the following code to the marco editor to create code-behind files for resources when you save the file (or create the build). This code is not very good, only a test (grrrrr) ... but is working on my environment.
Private Sub DocumentEvents_DocumentSaved(ByVal Document As EnvDTE.Document) Handles DocumentEvents.DocumentSaved
Dim s As Solution
Dim p As Project
Dim vs As VSProject
Dim r As Reference
Dim aProp As EnvDTE.Property
Dim props As Properties
Dim projitem As ProjectItem
Dim w As TextWriter
Dim doc As XmlDocument
Dim n, n_name, n_type, n_descr As XmlNode
Dim resourcename, resourcetype, resourcedescr As String
Dim codebehind As String
Dim AssemblyName As String
Dim resource As String
If (Document.FullName.ToLower().EndsWith(".resx") = True) Then
resource = System.IO.Path.GetFileNameWithoutExtension(Document.FullName)
codebehind = Document.FullName & ".cs"
' load resource xml file
doc = New XmlDocument
doc.Load(Document.FullName)
' create code-behind source code
Dim sb As New System.Text.StringBuilder
sb.Append("using System;" & Chr(13))
sb.Append("using System.ComponentModel;" & Chr(13))
sb.Append("using System.Reflection;" & Chr(13))
sb.Append("" & Chr(13))
sb.Append("namespace #ASSEMBLYNAME#" & Chr(13))
sb.Append("{" & Chr(13))
sb.Append(Chr(9) & "sealed class " & resource & "" & Chr(13))
sb.Append(Chr(9) & "{" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "private static System.Resources.ResourceManager _resMgr;" & Chr(13))
sb.Append("" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "private " & resource & "()" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "{" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "}" & Chr(13))
sb.Append("" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "public static System.Resources.ResourceManager ResourceManager" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "{" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & "get" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & "{" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & Chr(9) & "if(_resMgr == null)" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & Chr(9) & "{" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & Chr(9) & Chr(9) & "System.Resources.ResourceManager temp = new System.Resources.ResourceManager(""#ASSEMBLYNAME#." & resource & """, Assembly.GetExecutingAssembly());" & Chr(13))
sb.Append("" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & Chr(9) & Chr(9) & "System.Threading.Thread.MemoryBarrier();" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & Chr(9) & Chr(9) & "_resMgr = temp;" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & Chr(9) & "}" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & Chr(9) & "return _resMgr;" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & "}" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "}" & Chr(13))
For Each n In doc.DocumentElement.SelectNodes("data")
resourcename = ""
resourcetype = ""
resourcedescr = ""
n_name = n.SelectSingleNode("@name")
If (n_name Is Nothing = False) Then
resourcename = n_name.InnerText.Replace(" ", "_")
End If
n_type = n.SelectSingleNode("@type")
If (n_type Is Nothing = False) Then
resourcetype = n_type.InnerText
End If
n_descr = n.SelectSingleNode("comment")
If (n_descr Is Nothing = False) Then
resourcedescr = n_descr.InnerText
End If
If (resourcename <> "" And resourcetype <> "") Then
sb.Append(Chr(9) & Chr(9) & "///<summary>" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "///" & resourcedescr & Chr(13))
sb.Append(Chr(9) & Chr(9) & "///</summary>" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "public static " & resourcetype & " " & resourcename & "" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "{" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & "get" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & "{" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & Chr(9) & "return (" & resourcetype & ")ResourceManager.GetObject(""" & resourcename + """);" & Chr(13))
sb.Append(Chr(9) & Chr(9) & Chr(9) & "}" & Chr(13))
sb.Append(Chr(9) & Chr(9) & "}" & Chr(13))
End If
Next
sb.Append(Chr(9) & "}" & Chr(13))
sb.Append("}" & Chr(13))
sb.Append("" & Chr(13))
' create an empy file
w = File.CreateText(codebehind)
w.Close()
' search if the code-behind file is already in the project
s = DTE.Solution
For Each p In s.Projects
vs = p.Object
props = vs.Project.Properties
For Each aProp In props
If (aProp.Name = "AssemblyName") Then
AssemblyName = aProp.Value
End If
Next
For Each projitem In vs.Project.ProjectItems
If projitem.FileNames(0).ToLower() = Document.FullName.ToLower() Then
If projitem.ProjectItems.Count = 0 Then
projitem.ProjectItems.AddFromFile(codebehind)
End If
End If
Next
Next
w = File.CreateText(codebehind)
w.Write(sb.ToString().Replace("#ASSEMBLYNAME#", AssemblyName))
w.Close()
End If
End Sub
4 Comments
Comments have been disabled for this content.
Ingo Raelphel said
Do you have this code also in C#? I hate VB.NET!!!
Michael Schwarz said
@Ingo: No, sorry! The macro editor only allows Visual Basic .NET. At the moment I am looking for creating a Visual Studio Add-In that will be written in C#.
Eli Robillard said
I realize it isn't the goal of the post, but using concatenation within a Stringbuilder completely defeats the advantages using a SB. It's 100% more efficient to put each element to concatenate in its own Append. Otherwise, nice!
Michael Schwarz said
;)
You are right... it was only a fast test.