T4(文本模板转换工具包)用于根据 C# 中的基本类型列表(例如 PointI32、PointF32 等)生成一组类型

发布于 2024-08-21 11:48:16 字数 850 浏览 10 评论 0原文

类似于 用于在 C++/CLI 中基于基本类型列表(例如 PointI32、PointF32 等)生成一组类型的 Boost 预处理器库 我问如何生成:

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

    // Other code
};

对于不同的基本 (POD) 数据类型,例如:

PointF32, PointF64, PointI32 etc.

使用 T4 ( Visual Studio 2008 或更高版本中的文本模板转换工具包)。

请参阅http://www.olegsych.com/2007/12/ text-template-transformation-toolkit/http://msdn .microsoft.com/en-us/library/bb126445.aspx

Similar to Boost Preprocessor library for generating a set of types based on a list of basic types e.g. PointI32, PointF32 etc. in C++/CLI I am asking how to generate:

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

    // Other code
};

for different basic (POD) data types e.g.:

PointF32, PointF64, PointI32 etc.

using T4 (Text Template Transformation Toolkit) in Visual Studio 2008 or later.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷路的信 2024-08-28 11:48:16

好吧,我自己有答案。我创建了以下 T4 包含文件:

  • SignedIntegersSuffices.ttinclude
  • UnsignedIntegersSuffices.ttinclude
  • IntegersSuffices.ttinclude
  • FloatsSuffices.ttinclude
  • < code>BasicTypesSuffices.ttinclude

,然后实际的 T4 模板是 PointTypes.tt。这些文件只需添加到 C# 项目中,每当保存 .tt 文件时,Visual Studio 就会检测 .tt 并生成匹配的 PointTypes.cs 文件。

下面列出了这些文件。

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; }
    }
}

非常简单且非常有效。当然,现在这可以使用泛型等来完成,但这不是这里的重点。这是多种基本类型的代码生成的简单示例。

欢迎提出改进或类似的意见。

Well, I have the answer my self. I have created the following T4 include files:

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

and then the actual T4 template is PointTypes.tt. These files are simply added to a C# project and Visual Studio will detect the .tt and generate a matching PointTypes.cs file, whenever the .tt file is saved.

These files are listed in the following.

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

And finally the actual template file 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; }
    }
<#
    }
#>
}

The output file PointTypes.cs will then look like this:

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; }
    }
}

Pretty simple and quite effective. Now, of course, this could have been done using generics etc, but that is not the point here. This is meant as a simple example of code generation for multiple basic types.

Comments to improve this or similar are welcomed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文