Open utterances-bot opened 5 years ago
CompilingException找不到。
呀!不好意思 @zhusheping 忽略这个类型,你自己随便抛出一个自己的类型。这是我自己定义的异常类型,在 https://github.com/dotnet-campus/SourceFusion 项目中定义的。
谢谢啦。 从你的https://blog.walterlv.com上面学到了不少知识。最近项目上要用到Roslyn动态执行,在使用中有问题,能否请教你?
比如有个类:
public class Test
{
public string Say(string s)
{
Console.WriteLine(s);return s;
}
public T Get
动态脚本里面是这几句话
var test = New Test();
var str = test.Say("hello");
int i = test.Get
我如何用CSharpSyntaxRewriter 来动态的改动让他们执行:
var test = New Test();
var str = test.Say("hello",1);
int i = test.Get
这样做看起来没什么意义,但只是为了简化问题,实际上是有应用场景的。
Deep Mind Solutions. We Help .Solutions for Printing Industry
Name:朱社平
Mob: +8618993794536 zhusp@deepmind.cn Guangzhou, China
------------------ 原始邮件 ------------------ 发件人: "walterlv"notifications@github.com; 发送时间: 2019年4月28日(星期天) 上午8:39 收件人: "walterlv/BlogComments"BlogComments@noreply.github.com; 抄送: "阿平"790978@qq.com; "Mention"mention@noreply.github.com; 主题: Re: [walterlv/BlogComments] post/compile-and-invoke-code-using-roslyn(#7)
呀!不好意思 @zhusheping 忽略这个类型,你自己随便抛出一个自己的类型。这是我自己定义的异常类型,在 dotnet-campus/SourceFusion: SourceFusion is a pre-compile framework based on Roslyn. It helps you to build high-performance .NET code. 项目中定义的。
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
@zhusheping 如果你是希望运行时动态执行,建议考虑 Emit 或者表达式树:
如果是编译期间动态改变,其实这么简单的,只需要字符串(正则)匹配一下就好了。
如果够复杂,需要使用 Roslyn 语法重写的话,你需要 override 查找 InvocationExpression
的方法,然后依次找 InvocationExpression
,ArgumentList
,然后调用 Update
修改此 ArgumentList
。
关于找什么的问题,可以阅读:
感谢回复。 我找到了部分实现代码。
string originalText = System.IO.File.ReadAllText(@"C:\Users\yalin\Desktop\aaa.cs");
var syntaxTree = CSharpSyntaxTree.ParseText(originalText);
var syntaxRoot = syntaxTree.GetCompilationUnitRoot();
var invocationExpressions = syntaxRoot.DescendantNodes().OfType<InvocationExpressionSyntax>();
foreach (var item in invocationExpressions)
{
var argus = item.ArgumentList.AddArguments(
SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(2)))
);
var ss = item.Update(item, argus);
}
只是不知道如何更新回ArgumentList。我试过update,但好像不行。这个语法上不太好试出来。
@zhusheping Roslyn 的语法树是 Immutable 不可变的,你调用 Update 方法后不会修改源树,而是会生成一个新树。所以你需要将新树存下来输出成文本才可以。
CSharpSyntaxTree.ParseText(code) 这个方法执行一次就增加10M的内存,如果大量调用,GC量很大,性能很是个问题,可以怎么优化下,内存少占一些吗
@shibox 所以,不要总是通过 ParseText
来解析一段文本,这样确实每次都会创建新的语法节点,建议使用工作区 Workspace
来分析。
Roslyn 中使用红绿树来尽可能复用生成的语法节点,见下文。此复用在工作区范围生效。如果你每次都解析文本将不会复用。
下面是使用工作区来分析代码的例子:
另外,如果在写 Visual Studio 的插件,那么 Roslyn API 的实现已经做好了复用语法节点,只需要重写就好了。
public class GenericGenerator { private static readonly string GeneratedAttribute = @"[System.CodeDom.Compiler.GeneratedCode(""walterlv"", ""1.0"")]";
public string Transform(string originalCode, int genericCount)
{
if (genericCount == 1)
{
return originalCode;
}
var content = originalCode
// 替换泛型。
.Replace("<out T>", FromTemplate("<{0}>", "out T{n}", ", ", genericCount))
.Replace("Task<T>", FromTemplate("Task<({0})>", "T{n}", ", ", genericCount))
.Replace("Func<T, Task>", FromTemplate("Func<{0}, Task>", "T{n}", ", ", genericCount))
.Replace(" T, Task>", FromTemplate(" {0}, Task>", "T{n}", ", ", genericCount))
.Replace("(T, bool", FromTemplate("({0}, bool", "T{n}", ", ", genericCount))
.Replace("var (t, ", FromTemplate("var ({0}, ", "t{n}", ", ", genericCount))
.Replace(", t)", FromTemplate(", {0})", "t{n}", ", ", genericCount))
.Replace("return (t, ", FromTemplate("return ({0}, ", "t{n}", ", ", genericCount))
.Replace("<T>", FromTemplate("<{0}>", "T{n}", ", ", genericCount))
.Replace("(T value)", FromTemplate("(({0}) value)", "T{n}", ", ", genericCount))
.Replace("(T t)", FromTemplate("({0})", "T{n} t{n}", ", ", genericCount))
.Replace("(t)", FromTemplate("({0})", "t{n}", ", ", genericCount))
.Replace("var t =", FromTemplate("var ({0}) =", "t{n}", ", ", genericCount))
.Replace(" T ", FromTemplate(" ({0}) ", "T{n}", ", ", genericCount))
.Replace(" t;", FromTemplate(" ({0});", "t{n}", ", ", genericCount))
// 生成 [GeneratedCode]。
.Replace(" public interface ", $" {GeneratedAttribute}{System.Environment.NewLine} public interface ")
.Replace(" public class ", $" {GeneratedAttribute}{System.Environment.NewLine} public class ")
.Replace(" public sealed class ", $" {GeneratedAttribute}{System.Environment.NewLine} public sealed class ");
return content.Trim();
}
private static string FromTemplate(string template, string part, string seperator, int count)
{
return string.Format(template,
string.Join(seperator, Enumerable.Range(1, count).Select(x => part.Replace("{n}", x.ToString()))));
}
}
是seperator而不是separator
@zhenlei520 非常感谢您帮助我指出博客里的问题!
正确的写法是 separator
(我的所有博客里十多处都是这么写的),错误的写法是 seperator
(我有两处这么写错了,其中一处被您指出了)。
separator
好吧 那可能是改博客的时候只改了调用而没改参数名
Roslyn 入门:使用 .NET Core 版本的 Roslyn 编译并执行跨平台的静态的源码 - walterlv
Roslyn 入门:使用 .NET Core 版本的 Roslyn 编译并执行跨平台的静态的源码
https://blog.walterlv.com/post/compile-and-invoke-code-using-roslyn.html