Myriad.Core 0.8.3
dotnet add package Myriad.Core --version 0.8.3
NuGet\Install-Package Myriad.Core -Version 0.8.3
<PackageReference Include="Myriad.Core" Version="0.8.3" />
paket add Myriad.Core --version 0.8.3
#r "nuget: Myriad.Core, 0.8.3"
// 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。
通过 MSBuild 使用
要通过 Myriad 的 MSBuild 支持使用 Myriad,您需要添加 Myriad.Core
和 Myriad.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 还可以生成记录和单案例区分联合的 透镜。透镜是一种 对,其中包含对类型的一个属性的 getter
和 setter
。给定对象 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
如何构建和测试
- 请确保已安装.NET Core SDK - 在
global.json
中检查所需版本 - 运行
dotnet tool restore
- 运行
dotnet build -c Release -t:Build
如何发布新版本
- 更新
CHANGELOG.md
,添加新条目(## [0.X.X]
)并提交它。 - 创建版本标签(
git tag v0.X.X
) - 将
VersionPrefix
更新到Directory.Build.props
中,以便与上面的标签匹配。 - 运行
dotnet build -t:Pack
以创建nuget包并本地测试/检查它。 - 将标签推送到repo中(
git push origin v0.X.X
)-这将启动CI流程,创建GitHub发布,并将生成的NuGet包放在其中 - 将生成的包上传到NuGet.org
另请参阅
外部插件
以下是已经构建的外部插件列表
产品 | 版本 兼容和额外的计算目标框架版本。 |
---|---|
.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. |
-
.NETStandard 2.1
- Fantomas.Core (≥6.1.1)
-
net6.0
- Fantomas.Core (≥6.1.1)
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 |