如何拦截、解析、编译?
这是我一段时间以来一直在努力解决的问题。我需要一种方法来在编译时用模板中的解析代码替换方法中的代码(想到 PostSharp)或创建动态代理(Linfu 或 Castle)。因此,给定这样的源代码,
[Template]
private string GetSomething()
{
var template = [%=Customer.Name%]
}
我需要将其编译成这样。
private string GetSomething()
{
MemoryStream mStream = new MemoryStream();
StreamWriter writer = new StreamWriter(mStream,System.Text.Encoding.UTF8);
writer.Write(@"" );
writer.Write(Customer.Name);
StreamReader sr = new StreamReader(mStream);
writer.Flush();
mStream.Position = 0;
return sr.ReadToEnd();
}
使用什么技术并不重要。我尝试使用 PostSharp 的 ImplementMethodAspect 但一无所获(由于缺乏经验)。我也研究过Linfu框架。有人可以建议其他方法或方式来做到这一点,我真的很感激。我的整个项目都取决于此。
假设:
- 代码可以出现在任何类中。
- 模板代码将始终使用属性 [Template] 进行注释,
- 模板方法将始终返回字符串。
将代码从一种形式解析为另一种形式已经完成。现在我只需要一个方法来替代它。
“牛肉”示例:
[Test]
public void can_parse_csharp_code_template3()
{
var template = @"<template> [%= GetUsing() %]
namespace [%= GetModelNamespaceName(.metaPackage) %]
{
[%= .visibility.ToString().ToLower() %] class [%= .Name %] : INotifyPropertyChanged [%= If(.IsPersistent, "", PersistenObject"", """") %]
{
#region Constructors
[%= ConstructorTemplate.Create(metaObject).GetParameterlessConstructorCode %]
#endregion
#region Attributes
[%= From attribute In metaObject.attributes _
Select (AttributeTemplate.Create(attribute).GetSourceCode) %]
#endregion
#region Relationships
[%= From relationship As Relationship In metaObject.relationships _
Select (RelationshipTemplateFactory.CreateFor(relationship).GetSourceCode()) %]
#endregion
#region Methods
[%= From operation In metaObject.operations _
Select (MethodTemplate.Create(operation).GetSourceCode) %]
#endregion
#region ""INotifyPropertyChanged""
[%= GetOnPropertyChanged() %]
#endregion
}
}</template>";
Console.WriteLine(TemplateParser.GetParsedResult(template));
}
This is a problem I've been struggling to solve for a while. I need a way to either replace code in the method with a parsed code from the template at compile time (PostSharp comes to mind) or to create a dynamic proxy (Linfu or Castle). So given a source code like this
[Template]
private string GetSomething()
{
var template = [%=Customer.Name%]
}
I need it to be compiled into this
private string GetSomething()
{
MemoryStream mStream = new MemoryStream();
StreamWriter writer = new StreamWriter(mStream,System.Text.Encoding.UTF8);
writer.Write(@"" );
writer.Write(Customer.Name);
StreamReader sr = new StreamReader(mStream);
writer.Flush();
mStream.Position = 0;
return sr.ReadToEnd();
}
It is not important what technology is used. I tried with PostSharp's ImplementMethodAspect but got nowhere (due to lack of experience with it). I also looked into Linfu framework. Can somebody suggest some other approach or way to do this, I would really appreciate. My whole project depends on this.
Assumptions:
- Code can appear in any class.
- Template code will always be annotated with attribute [Template]
- Template method will always return string.
Parsing of the code from one form to another is already done. Now I just need a way to replace it.
"Beefer" example:
[Test]
public void can_parse_csharp_code_template3()
{
var template = @"<template> [%= GetUsing() %]
namespace [%= GetModelNamespaceName(.metaPackage) %]
{
[%= .visibility.ToString().ToLower() %] class [%= .Name %] : INotifyPropertyChanged [%= If(.IsPersistent, "", PersistenObject"", """") %]
{
#region Constructors
[%= ConstructorTemplate.Create(metaObject).GetParameterlessConstructorCode %]
#endregion
#region Attributes
[%= From attribute In metaObject.attributes _
Select (AttributeTemplate.Create(attribute).GetSourceCode) %]
#endregion
#region Relationships
[%= From relationship As Relationship In metaObject.relationships _
Select (RelationshipTemplateFactory.CreateFor(relationship).GetSourceCode()) %]
#endregion
#region Methods
[%= From operation In metaObject.operations _
Select (MethodTemplate.Create(operation).GetSourceCode) %]
#endregion
#region ""INotifyPropertyChanged""
[%= GetOnPropertyChanged() %]
#endregion
}
}</template>";
Console.WriteLine(TemplateParser.GetParsedResult(template));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(2)
DMS 解析您的文件,构建完整的抽象语法树,并允许您编写可以扩展文本中的点的自定义转换(大多数代码生成器(如 T4)所做的)或更重要的是替换任何构造(本地和/或分布在整个文本中)组成应用程序的文件集)以及您可能想要生成的任何其他代码。
您似乎对生成代码片段的元语言有一些了解,例如,
From operation In metaObject.operations _
Select (MethodTemplate.Create(operation).GetSourceCode)
据我所知,该元语言不是 C#。使用 DMS,您可以为元语言定义解析器,并在代码生成器遇到构造时将元语言处理成树。通过此类树上的小型解释器,您可以将元语言文本转换为生成感兴趣文本的生成器操作。
[我是 DMS 背后的首席技术官]。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
请查看 T4(文本模板转换工具包)。
Have a look at T4 (Text Template Transformation Toolkit).