我可以使用 roslyn 和新的 .net 项目格式在构建时创建类吗?
Posted
技术标签:
【中文标题】我可以使用 roslyn 和新的 .net 项目格式在构建时创建类吗?【英文标题】:Can I use roslyn and the new .net project format to create classes on build? 【发布时间】:2015-07-22 07:38:06 【问题描述】:我有一个项目使用新的 .net 项目格式(dnx
和 project.json
,目前使用带有 mono-1.0.0-beta4 的 dnvm
,一旦他们得到 dnu restore
工作,最终想使用 coreclr *NIX)。
我在使用 .net/C# 时遇到的一个常见问题是希望在编译时创建代码。例如,我有一个虚拟机,它有一个这样的辅助类:
public static class OpCodes
private readonly static IDictionary<byte, OpCode> _opcodes;
public static OpCode MOV get; private set;
public static OpCode ADD get; private set;
public static OpCode SUB get; private set;
static OpCodes()
// OpCode class contains info, e.g., the number of arguments
MOV = new OpCode(0x00, "MOV", 2);
ADD = new OpCode(0x01, "ADD", 0);
SUB = new OpCode(0x02, "SUB", 0);
_opcodes = new Dictionary<byte, OpCode>
MOV.Code, MOV ,
ADD.Code, ADD ,
SUB.Code, SUB ,
;
public static OpCode Get(byte code)
OpCode result;
if(_opcodes.TryGetValue(code, out result))
return result;
return null;
如您所见,那里有很多管道:
-
操作码列表
每个操作码的静态 Getter
一种通过二进制值查找 OpCode 的方法
我唯一应该创建的是#1,应用程序的实际内容。应该为我将其包装在字典中并创建静态 getter。
我知道“常规”Visual Studio 有 T4 模板,但这些模板在构建时运行起来很痛苦,而且似乎与 Visual Studio 绑定在一起,因此不再适用。
有什么我可以做的吗?我想我可以在 project.json 中创建自定义操作(例如,dnx . regenopcodes
)但我不知道我会在这里运行什么,因为我需要调用 Roslyn,找到 OpCodes 列表(也许做一个抽象 @987654327 @class),解析它,并为我生成具体的OpCodes
类。
或者,我可以创建一个 opcodes.xml 文件并使用普通文本解析从中创建一个 .cs,但我不确定在任何时候我如何配置它dnx . run
它首先运行我的生成器并然后做它通常做的任何事情。
【问题讨论】:
但是在哪里指定了那些必需的操作码? @Tigran 无论在哪里最容易让它们进入构建 :) 例如,internal abstract class OpCodeDefs private readonly OpCode[] OpCodes = new [] new OpCode(0x00, "MOV", 2)
或在外部文件 (opcodes.xml
) 中,或者实际上,任何对构建有用的东西。应用程序代码将专门使用生成的类,并且永远不需要知道源代码。
所以Dyamic
不是一个选项(通过解析“源”来构造真实对象),因为您需要类型安全。正确的 ?换句话说,您必须拥有static
方法(比如说)。
@Tigran 嗯...好点。动态可以工作,但这意味着放弃 IntelliSense 和运行时惩罚(过早的优化警报)。绝对是一种选择。
如果你正在转向代码生成,无论如何你都会失去智能感知。但是在代码生成的情况下,您可能会从编译时类型检查中受益,这是不可低估的,并且有点遗憾地忽略它,当我们仍然处于静态类型语言的舒适边界时,如 C#
。
【参考方案1】:
您可以添加预编译步骤,类似于 Razor 预编译视图的操作:https://github.com/aspnet/Mvc/blob/64e726d2b26422c5452475627e4afaba307edec3/src/Microsoft.AspNet.Mvc/RazorPreCompileModule.cs
这是另一个例子:https://github.com/aspnet/dnx/blob/e937e25ab3453ea86bda13c1297c41011dfda9de/ext/compiler/preprocess/Internalization.cs
这就是你连接它的方式https://github.com/aspnet/dnx/blob/3d20719b0a985b6960a3f87d9f5f9b6c3f71b7bc/src/Microsoft.Framework.Runtime/project.json#L16-L18
【讨论】:
谢谢,就这样!目前,这些包在主要 NuGet 提要中仍称为 .Interfaces,但我认为它们很快会重命名为 .Abstractions。 这个答案还有意义吗?看起来ICompileModule
已经消失了。
不再。 ICompileModule
不见了
我如何使用通过语法生成器生成的 c# 类在运行时通过 roslyn 将它们转储到 dll 中?以上是关于我可以使用 roslyn 和新的 .net 项目格式在构建时创建类吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 Visual Studio 2013 中使用 Roslyn 编译器
Roslyn Source Generator 未在 .net 框架 4.7.2 中生成任何源
使用基于Roslyn的编译时AOP框架来解决.NET项目的代码复用问题