T4 (Text Template Transformation Toolkit) для генерации набора типов на основе списка основных типов, например, PointI32, PointF32 и т. Д. В C # - PullRequest
1 голос
/ 12 февраля 2010

Аналогично Библиотека повышения препроцессора для генерации набора типов на основе списка основных типов, например, PointI32, PointF32 и т. Д. В C ++ / CLI Я спрашиваю, как создать:

struct Point##TYPE_SUFFIX_NAME
{
    TYPE X
    { get; set; }
    TYPE Y;
    { get; set; }

    // Other code
};

для различных базовых типов данных (POD), например ::1006*

PointF32, PointF64, PointI32 etc.

с использованием T4 (Transform Toolkit) в Visual Studio 2008 или более поздней версии.

См. http://www.olegsych.com/2007/12/text-template-transformation-toolkit/ и http://msdn.microsoft.com/en-us/library/bb126445.aspx

1 Ответ

2 голосов
/ 12 февраля 2010

Ну, у меня есть ответ сам. Я создал следующие файлы включения T4:

  • SignedIntegersSuffices.ttinclude
  • UnsignedIntegersSuffices.ttinclude
  • IntegersSuffices.ttinclude
  • FloatsSuffices.ttinclude
  • BasicTypesSuffices.ttinclude

, а затем фактический шаблон T4 - PointTypes.tt. Эти файлы просто добавляются в проект C #, и Visual Studio обнаружит .tt и сгенерирует соответствующий файл PointTypes.cs при каждом сохранении файла .tt.

Эти файлы перечислены ниже.

SignedIntegersSuffices.ttinclude

<#+
IEnumerable<KeyValuePair<string, string>> SignedIntegersSuffices()
{
    var signedIntegersSuffices = new KeyValuePair<string, string>[] { 
        new KeyValuePair<string, string>("sbyte", "I8"),
        new KeyValuePair<string, string>("short", "I16"),
        new KeyValuePair<string, string>("int", "I32"),
        new KeyValuePair<string, string>("long", "I64")
    };
    return signedIntegersSuffices;
}
#>

UnsignedIntegersSuffices.ttinclude

<#+
IEnumerable<KeyValuePair<string, string>> UnsignedIntegersSuffices()
{
    var signedIntegersSuffices = new KeyValuePair<string, string>[] { 
        new KeyValuePair<string, string>("byte", "UI8"),
        new KeyValuePair<string, string>("ushort", "UI16"),
        new KeyValuePair<string, string>("uint", "UI32"),
        new KeyValuePair<string, string>("ulong", "UI64")
    };
    return signedIntegersSuffices;
}
#>

IntegersSuffices.ttinclude

<#@ include file="SignedIntegersSuffices.ttinclude" #>
<#@ include file="UnsignedIntegersSuffices.ttinclude" #>
<#+
    // Insert any template procedures here
    IEnumerable<KeyValuePair<string, string>> IntegersSuffices()
    {
        var integersSuffices = SignedIntegersSuffices().Concat(UnsignedIntegersSuffices());
        return integersSuffices;
    }
#>

FloatsSuffices.ttinclude

<#+
    // Insert any template procedures here
    IEnumerable<KeyValuePair<string, string>> FloatsSuffices()
    {
        var floatsSuffices = new KeyValuePair<string, string>[] { 
            new KeyValuePair<string, string>("float", "F32"),
            new KeyValuePair<string, string>("double", "F64")
        };
        return floatsSuffices;
    }
#>

BasicTypesSuffices.ttinclude

<#@ include file="IntegersSuffices.ttinclude" #>
<#@ include file="FloatsSuffices.ttinclude" #>
<#+
    // Insert any template procedures here
    IEnumerable<KeyValuePair<string, string>> BasicTypesSuffices()
    {
        var basicTypesSuffices = IntegersSuffices().Concat(FloatsSuffices());
        return basicTypesSuffices;
    }
#>

И, наконец, фактический файл шаблона PointTypes.tt:

<#@ template inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" language="C#v3.5" debug="true" hostSpecific="true" #>
<#@ output extension=".cs" #>
<#@ Assembly Name="System.dll" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #> 
<#@ include file="BasicTypesSuffices.ttinclude" #>
namespace TextTemplatesTest
{
<#
    const string pointPrefix = "Point";
    foreach (var typeSuffix in BasicTypesSuffices())
    {
        string type = typeSuffix.Key;
        string suffix = typeSuffix.Value;
#>
    public struct <#= pointPrefix #><#= suffix #>
    {
        <#= pointPrefix #><#= suffix #>(<#= type #> x, <#= type #> y)
            : this()
        {
            X = x;
            Y = y;
        }

        public <#= type #> X
        { get; set; }
        public <#= type #> Y
        { get; set; }
    }
<#
    }
#>
}

Выходной файл PointTypes.cs будет выглядеть следующим образом:

namespace TextTemplatesTest
{
    public struct PointI8
    {
        PointI8(sbyte x, sbyte y)
            : this()
        {
            X = x;
            Y = y;
        }

        public sbyte X
        { get; set; }
        public sbyte Y
        { get; set; }
    }
    public struct PointI16
    {
        PointI16(short x, short y)
            : this()
        {
            X = x;
            Y = y;
        }

        public short X
        { get; set; }
        public short Y
        { get; set; }
    }
    public struct PointI32
    {
        PointI32(int x, int y)
            : this()
        {
            X = x;
            Y = y;
        }

        public int X
        { get; set; }
        public int Y
        { get; set; }
    }
    public struct PointI64
    {
        PointI64(long x, long y)
            : this()
        {
            X = x;
            Y = y;
        }

        public long X
        { get; set; }
        public long Y
        { get; set; }
    }
    public struct PointUI8
    {
        PointUI8(byte x, byte y)
            : this()
        {
            X = x;
            Y = y;
        }

        public byte X
        { get; set; }
        public byte Y
        { get; set; }
    }
    public struct PointUI16
    {
        PointUI16(ushort x, ushort y)
            : this()
        {
            X = x;
            Y = y;
        }

        public ushort X
        { get; set; }
        public ushort Y
        { get; set; }
    }
    public struct PointUI32
    {
        PointUI32(uint x, uint y)
            : this()
        {
            X = x;
            Y = y;
        }

        public uint X
        { get; set; }
        public uint Y
        { get; set; }
    }
    public struct PointUI64
    {
        PointUI64(ulong x, ulong y)
            : this()
        {
            X = x;
            Y = y;
        }

        public ulong X
        { get; set; }
        public ulong Y
        { get; set; }
    }
    public struct PointF32
    {
        PointF32(float x, float y)
            : this()
        {
            X = x;
            Y = y;
        }

        public float X
        { get; set; }
        public float Y
        { get; set; }
    }
    public struct PointF64
    {
        PointF64(double x, double y)
            : this()
        {
            X = x;
            Y = y;
        }

        public double X
        { get; set; }
        public double Y
        { get; set; }
    }
}

Довольно просто и довольно эффективно. Сейчас, конечно, это можно было бы сделать с помощью дженериков и т. Д., Но здесь дело не в этом. Это простой пример генерации кода для нескольких основных типов.

Комментарии для улучшения этого или аналогичного приветствуются.

...