Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

T4 namespace and type resolving

I'm trying to create T4 template that will take my app global Resources, loop through the static properties and create a static class with const string properties, so I would be able to get resource names as string by using the strong type.

Here's what I have now:

<#@ template debug="true" hostSpecific="true" #>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ output extension=".cs"#>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#  CodeGenerationTools code = new CodeGenerationTools(this);
    MetadataLoader loader = new MetadataLoader(this);
    CodeRegion region = new CodeRegion(this, 1);
    MetadataTools ef = new MetadataTools(this);
    string namespaceName = code.VsNamespaceSuggestion();
if (!String.IsNullOrEmpty(namespaceName))
{ #>
namespace <#=code.EscapeNamespace(namespaceName)#>
{
<#    PushIndent(CodeRegion.GetIndent(1));
} #>
    public static class ResourceStrings {
<#      var props = typeof(Resources).GetProperties(BindingFlags.Static);
        foreach (var prop in props) { #>
            public const string <#= prop.Name #> = "<#= prop.Name #>";
<#      } #>
    }
<# if (!String.IsNullOrEmpty(namespaceName))
{
    PopIndent(); #>
}
<# } #>
<#+
  // Insert any template procedures here
#>

The problem is that it just can't find the Resources namespace in the typeof(). The Resources namespace is the namespace of my Localize.designer.cs file (autogenerated file of Localize.resx).

What am I missing here?

like image 495
mare Avatar asked Dec 28 '22 01:12

mare


1 Answers

I just had a similar idea. I wanted to have a static class with const string values for my user settings in order to use a strong type rather than a string in Windows Forms Binding:

this.textBox1.DataBindings.Add("Text", Properties.Settings.Default, Properties.Settings.PropertyNames.SomeStringValue);

However, I figured out that a t4 template cannot access the types of the current project. You have to load the file with

<#@ assembly name="$(TargetPath)" #>

However, if you do that and regenerate your template you not rebuild your project since the file is in use unless you close visual studio.

Long story short,

I dropped this approach and now I read the app.config file by myself to get the data I need. Should be quite easy to modify to read the Resources.xml file instead.

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Xml.Linq" #>

<#
var xmlFile = Path.Combine(Path.GetDirectoryName(Host.TemplateFile), "..", "app.config");
var query = from x in XElement.Load(xmlFile).Element("userSettings").Element("Your.Namespace.Properties.Settings").Elements("setting")
            select x;
#>

namespace Your.Namespace.Properties
{
    public sealed partial class Settings
    {
        public static class PropertyNames
        {

        <# foreach (var item in query) { #>
        public static readonly string <#=item.Attribute("name").Value#> = @"<#=item.Attribute("name").Value#>";
        <# } #>

        }
    }
}
like image 140
Jürgen Steinblock Avatar answered Jan 08 '23 14:01

Jürgen Steinblock