Пространство имен T4 и разрешение типов - PullRequest
4 голосов
/ 05 февраля 2011

Я пытаюсь создать шаблон T4, который будет принимать глобальные ресурсы моего приложения, проходить через статические свойства и создавать статический класс со свойствами const string, чтобы я мог получить имена ресурсов как string, используясильный тип.

Вот что у меня сейчас:

<#@ 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
#>

Проблема в том, что он просто не может найти пространство имен Resources в typeof().Пространство имен Resources - это пространство имен моего файла Localize.designer.cs (автоматически сгенерированный файл Localize.resx).

Чего мне здесь не хватает?

Ответы [ 3 ]

5 голосов
/ 08 февраля 2011

У меня просто была похожая идея. Я хотел иметь статический класс со значениями константных строк для моих пользовательских настроек, чтобы использовать строгий тип, а не строку в привязке форм Windows:

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

Однако я понял, что шаблон t4 не может получить доступ к типам текущего проекта. Вы должны загрузить файл с

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

Однако, если вы сделаете это и создадите новый шаблон, вы не перестроите свой проект, поскольку файл используется, пока вы не закроете Visual Studio.

Короче говоря,

Я отбросил этот подход, и теперь я сам читаю файл app.config, чтобы получить нужные мне данные. Должно быть довольно легко изменить, чтобы вместо этого прочитать файл Resources.xml.

<#@ 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#>";
        <# } #>

        }
    }
}
2 голосов
/ 30 мая 2012

Вы можете получить ссылку на текущее пространство имен, используя следующее:

<#+
    // other template code here...
    static string CurrentNamespace = System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint").ToString();

И использовать его в выводе шаблона следующим образом:

namespace <#=CurrentNamespace #>
{
    public static class MyGenerateClass
    {
       // other generated code here...
2 голосов
/ 05 сентября 2011

Попробуйте использовать T4Toolbox и директиву Volatile Assembly.

<#@ VolatileAssembly processor="T4Toolbox.VolatileAssemblyProcessor"
Name="<Your assembly fully qualified name that you are concerned about locking but need a self reference to>"#>

Это создаст теневую копию сборки для использования для T4.

Вам нужно скачать и установить T4Toolbox, чтобы это работало.

http://t4toolbox.codeplex.com/

...