Myriad.Core 0.8.3

dotnet add package Myriad.Core --version 0.8.3                
NuGet\Install-Package Myriad.Core -Version 0.8.3                
此命令旨在在 Visual Studio 的包管理器控制台中使用,因为它使用 NuGet 模块的Install-Package版本。
<PackageReference Include="Myriad.Core" Version="0.8.3" />                
对于支持PackageReference的项目,将此 XML 节点复制到项目文件中以引用此包。
paket add Myriad.Core --version 0.8.3                
#r "nuget: Myriad.Core, 0.8.3"                
#r 指令可用于 F# Interactive 和 Polyglot Notebooks。将其复制到交互式工具或脚本的源代码中以引用包。
// Install Myriad.Core as a Cake Addin
#addin nuget:?package=Myriad.Core&version=0.8.3

// Install Myriad.Core as a Cake Tool
#tool nuget:?package=Myriad.Core&version=0.8.3                

Myriad

Myriad 是一个代码生成器。它可处理任意文件,库提供不同的机制以允许在文件(无论文件是 F# 源文件还是简单的文本文件)响应下生成 F# 代码。

可以从 MSBuild 扩展或 CLI 工具中使用 Myriad。

Myriad 的理念是在尽可能简化的前提下,实现 F# 中的元编程。通过 F# 元编程,我指的是使用 F# 本地类型(如区分联合和记录)来生成惯用 F# 代码,这是使用 F# 类型提供器等工具不可能完成的,这些工具仅输出基本的 .NET 类。

Myriad 是我在与 F# 的类型提供程序和其他元编程功能(如引言和 AST 操作)一起工作时发展起来的理念的进化。Myriad 旨在通过 Myriad 插件轻松扩展编译器。Myriad 提供了一种扩展编译器的方法,该方法不是修改或调整类型提供程序,也不需要长时间等待 F# 语言的改进。您编写一个工作在 AST 输入片段上的 Myriad 插件,并供应 AST 输出,最终形式是构建到您的项目中的源代码。这使得编译器除了允许工具有效地操作之外,还可以优化生成的输出。

如果您想贡献代码,那是非常好的,请查看问题和创建一个 PR。

如果您喜欢这个存储库,并且想要表达您的赞赏等,我确实有 Ko-fi。

ko-fi

通过 MSBuild 使用

要通过 Myriad 的 MSBuild 支持使用 Myriad,您需要添加 Myriad.CoreMyriad.Sdk 包引用。

    <ItemGroup>
      <PackageReference Include="Myriad.Core" Version="0.5.0" />
      <PackageReference Include="Myriad.Sdk" Version="0.5.0" />
    </ItemGroup>

使用通常的 Compile 元素来指定输入文件。

<Compile Include="Library.fs"/>
<Compile Include="Generated.fs">
    <MyriadFile>Library.fs</MyriadFile>
</Compile>

这是一个配置 Myriad 的示例,以便使用 Library.fs 作为输入到 Myriad 的输入,将名为 Generated.fs 的文件包含在构建中。

还可以将生成的内容追加到输入文件。

<Compile Include="Library.fs">
    <MyriadInlineGeneration>true</MyriadInlineGeneration>
</Compile>

Myriad 通过插件生成代码工作。Myriad 包括一个名为 fields 的插件,该插件从名称相同的 OCaml 的 ppx_fields_conv 插件中汲取灵感。

本例中的输入文件 Library.fs 的样子如下

namespace Example
open Myriad.Plugins

[<Generator.Fields "fields">]
type Test1 = { one: int; two: string; three: float; four: float32 }
type Test2 = { one: Test1; two: string }

使用属性来告知代码生成器哪些输入 AST 的一部分将由插件处理。如果您有多个记录,并且只想让 fields 插件操作 Test1,则可以像示例中那样使用属性,只为 Test1 应用 Generator.Fields。注意,如果您想要的插件只需要整个输入 AST,那么不需要提供输入。Myriad 旨在成为一个库,而不是一个将您绑定到输入和生成代码机制的全框架。传递给属性 "fields" 的参数指定了用于插件的 myriad.toml 文件中的配置部分。在这个例子中,使用了 fields,并且 myriad.toml 文件如下所述

[fields]
namespace = "TestFields"

这指定了用于插件的名字空间,在这种情况下是 "TestFields"。

本例中的 fields 插件将在预构建时生成以下代码并编译到您的程序集

//------------------------------------------------------------------------------
//        This code was generated by myriad.
//        Changes to this file will be lost when the code is regenerated.
//------------------------------------------------------------------------------
namespace rec TestFields

module Test1 =
    open Example

    let one (x : Test1) = x.one
    let two (x : Test1) = x.two
    let three (x : Test1) = x.three
    let four (x : Test1) = x.four

    let create (one : int) (two : string) (three : float) (four : float32) : Test1 =
        { one = one
          two = two
          three = three
          four = four }

    let map (mapone : int -> int) (maptwo : string -> string) (mapthree : float -> float) (mapfour : float32 -> float32) (record': Test1) =
      { record' with
          one = mapone record'.one
          two = maptwo record'.two
          three = mapthree record'.three
          four = mapfour record'.four }

fields 插件为输入记录中的每个字段生成一个 map,一个接受每个字段的 create 函数,以及一个接受输入记录中的每个字段的一个函数的 map 函数。

对于每个字段的 map 函数在只想使用记录中的单个字段作为 lambda(如记录列表)的情况中非常有用。

let records = [{one = "a"; two = "aa"; three = 42.0; four = 172.0f}
               {one = "b"; two = "bb"; three = 42.0; four = 172.0f}]
 records |> List.sortBy Test1.one

透镜插件

Myriad 还可以生成记录和单案例区分联合的 透镜。透镜是一种 ,其中包含对类型的一个属性的 gettersetter。给定对象 Lens 允许您获取属性的值或更新它,创建一个新的对象。透镜的优势在于能够将它们结合起来读取或更新对象的嵌套字段。

要为您的类型创建透镜,首先将 Generator.Lenses 属性注释到您想要生成透镜的类型。

[<Generator.Lenses("lens")>]
type Record =
    { one: int
      two: string }

Myriad 将生成以下代码

module RecordLenses =
    let one = (fun (x: Test1) -> x.one), (fun (x: Test1) (value: int) -> { x with one = value })
    let two = (fun (x: Test1) -> x.two), (fun (x: Test1) (value: string) -> { x with two = value })

通常,透镜被定义为一个包含 getter 和 setter 对的单案例联合。Myriad 还能够添加杜康的构造函数的调用。

为了实现这一点,请使用Lens属性来装饰您的类型,指定DU构造函数的名称:[<Generator.Lenses("Lens")>],Myriad将生成此代码

module RecordLenses =
    let one = Lens((fun (x: Test1) -> x.one), (fun (x: Test1) (value: int) -> { x with one = value }))
    let two = Lens((fun (x: Test1) -> x.two), (fun (x: Test1) (value: string) -> { x with two = value }))

可以以多种方式提供DU构造函数的名称

  • 作为字符串:[<Generator.Lenses("lens", "Lens")>];
  • 或作为类型:[<Generator.Lenses("lens", typedefof<Lens<_, _>>)>][<Generator.Lenses(typeof<Lens<_, _>>)>].

如果Lens类型与带属性的类型位于不同的命名空间/模块中,请提供Lens构造函数的完整名称:[<Generator.Lenses("Namespace.And.Module.Of.Lens")>].


下面的fsproj是详细信息

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <Compile Include="Library.fs" />
        <Compile Include="Generated.fs">
            <MyriadFile>Library.fs</MyriadFile>
        </Compile>
    </ItemGroup>
    <ItemGroup>
      <PackageReference Include="Myriad.Core" Version="0.5.0" />
      <PackageReference Include="Myriad.Sdk" Version="0.5.0" />
    </ItemGroup>
</Project>

插件

Myriad的插件是通过在项目中包含nuget包来提供的。nuget基础设施提供必要的MSBuild props和targets,以便插件自动由Myriad使用。可以使用字段插件来源作为编写插件的参考,直到创建了更多关于编写插件的详细信息。

插件的命名

如果您制作了一个插件,一个非正式的命名约定是使用:{{OwnerNamespace}}.Myriad.Plugin

使用外部插件

为了使用未包含在Myriad_Plugins包中的外部插件,必须将它们注册到Myriad中。如果您正在使用CLI工具,则可以通过使用--plugin <path to dll>命令行参数来执行此操作。如果您正在使用MSBuild,则可以通过将MyriadSdkGenerator属性添加到您的项目文件中来实现。

<ItemGroup>
    <MyriadSdkGenerator Include="<path to plugin dll>" />
</ItemGroup>

例如,如果您有一个如下所示的项目布局

\src
-\GeneratorLib
 - Generator.fs
 - Generator.fsproj
-\GeneratorTests
 - Tests.fs
 - GeneratorTests.fsproj

您需要将以下内容添加到Generator.fsproj中

  <ItemGroup>
    <Content Include="build\Generator.props">
      <Pack>true</Pack>
      <PackagePath>%(Identity)</PackagePath>
      <Visible>true</Visible>
    </Content>
  </ItemGroup>

然后添加一个名为build的新文件夹,其中包含Generator.props文件

<Project>
    <ItemGroup>
        <MyriadSdkGenerator Include="$(MSBuildThisFileDirectory)/../lib/netstandard2.1/Generator.dll" />
    </ItemGroup>
</Project>

通常还要使用额外的props文件(在本示例中,该文件将是Generator.InTest.props)来简化测试。与测试匹配的.fsproj将是类似于以下的内容

<Project>
    <ItemGroup>
        <MyriadSdkGenerator Include="$(MSBuildThisFileDirectory)/../bin/$(Configuration)/netstandard2.1/Generator.dll" />
    </ItemGroup>
</Project>

请注意,Include路径是指向本地而不是nuget包的文件夹结构内的位置。

在您的测试fsproj中,您需要添加以下内容以允许本地使用插件而不是消耗nuget包


<Import Project="<Path to Generator plugin location>\build\Myriad.Plugins.InTest.props" />

调试

要调试Myriad,可以使用以下两个命令行选项

  • --verbose — 将诊断日志写入标准输出
  • --wait-for-debugger — 使得Myriad等待调试器附加到Myriad进程

可以通过MSBuild中的<MyriadSdkVerboseOutput>true</MyriadSdkVerboseOutput><MyriadSdkWaitForDebugger>true</MyriadSdkWaitForDebugger>属性触发这些选项。

Nuget

Myriad的nuget包可以在以下位置找到:Nuget包

Dotnet模板

Myriad插件/生成器的dotnet模板可以在以下位置找到

#install dotnet template
dotnet new -i Myriad.Templates

#create myriad generator from the template
dotnet new myriadgenerator -n myMyriadPlugin

如何构建和测试

  1. 请确保已安装.NET Core SDK - 在global.json中检查所需版本
  2. 运行dotnet tool restore
  3. 运行dotnet build -c Release -t:Build

如何发布新版本

  1. 更新CHANGELOG.md,添加新条目(## [0.X.X])并提交它。
  2. 创建版本标签(git tag v0.X.X
  3. VersionPrefix更新到Directory.Build.props中,以便与上面的标签匹配。
  4. 运行dotnet build -t:Pack以创建nuget包并本地测试/检查它。
  5. 将标签推送到repo中(git push origin v0.X.X)-这将启动CI流程,创建GitHub发布,并将生成的NuGet包放在其中
  6. 将生成的包上传到NuGet.org

另请参阅

外部插件

以下是已经构建的外部插件列表

SqlHyra JsonWrapper TypeSafeInternals

产品 兼容和额外的计算目标框架版本。
.NET net5.0 已计算。 net5.0-windows 已计算。 net6.0 兼容。 net6.0-android 已计算。 net6.0-ios 已计算。 net6.0-maccatalyst 已计算。 net6.0-macos 已计算。 net6.0-tvos 已计算。 net6.0-windows 已计算。 net7.0 已计算。 net7.0-android 已计算。 net7.0-ios 已计算。 net7.0-maccatalyst 已计算。 net7.0-macos 已计算。 net7.0-tvos 已计算。 net7.0-windows 已计算。 net8.0 已计算。 net8.0-android 已计算。 net8.0-browser 已计算。 net8.0-ios 已计算。 net8.0-maccatalyst 已计算。 net8.0-macos 已计算。 net8.0-tvos 已计算。 net8.0-windows 已计算。
.NET Core netcoreapp3.0 已计算。 netcoreapp3.1 已计算。
.NET Standard netstandard2.1 兼容。
MonoAndroid monoandroid 已计算。
MonoMac monomac 已计算。
MonoTouch monotouch 已计算。
Tizen tizen60 已计算。
Xamarin.iOS xamarinios 已计算。
Xamarin.Mac xamarinmac 已计算。
Xamarin.TVOS xamarintvos was computed.
Xamarin.WatchOS xamarinwatchos was computed.
兼容的目标框架
包含的目标框架(在包中)
了解有关目标框架.NET Standard的更多信息。

NuGet 库包 (3)

显示依赖 Myriad.Core 的前 3 个 NuGet 库包

下载
Myriad.Plugins

内置 Myriad 插件集合

BinaryDefense.Myriad.Plugins.JsonWrapper

一个用于 [Myriad](https://github.com/MoiraeSoftware/myriad) 的插件,该插件根据模式生成围绕 JToken 的静态类型无损包装。

TheAngryByrd.Myriad.Plugins.TypeSafeInternals

TheAngryByrd.Myriad.Plugins.TypeSafeInternals 使用 Myriad 生成类型安全的反射调用到内部函数/属性/方法。

GitHub 仓库

此包没有用于任何流行的 GitHub 仓库。

版本 下载 最后更新
0.8.3 8,190 9/8/2023
0.8.2 1,406 2/10/2023
0.8.1 4,708 5/13/2022
0.8.0 741 5/4/2022
0.7.4 1,518 10/29/2021
0.7.3 450 10/28/2021
0.7.3-alpha 272 10/28/2021
0.7.2 512 10/28/2021
0.7.1 807 10/26/2021
0.7.0 415 10/21/2021
0.6.4 450 10/11/2021
0.6.3 428 9/22/2021
0.6.2 466 9/17/2021
0.6.1 427 9/17/2021
0.6.0 518 9/9/2021
0.5.4 517 9/2/2021
0.5.3 2,262 5/21/2021
0.5.1 784 4/15/2021
0.5.0 2,921 12/22/2020
0.4.1 873 9/23/2020
0.4.0 922 7/21/2020
0.2.8 964 6/5/2020
0.2.7 1,161 5/18/2020
0.2.6 656 5/13/2020
0.2.4 589 11/3/2019
0.2.3 509 11/3/2019
0.2.2 532 11/2/2019
0.2.1 520 11/2/2019
0.2.0 497 10/23/2019