如何拦截、解析、编译?

发布于 08-28 04:00 字数 2281 浏览 13 评论 0原文

这是我一段时间以来一直在努力解决的问题。我需要一种方法来在编译时用模板中的解析代码替换方法中的代码(想到 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框架。有人可以建议其他方法或方式来做到这一点,我真的很感激。我的整个项目都取决于此。

假设:

  1. 代码可以出现在任何类中。
  2. 模板代码将始终使用属性 [Template] 进行注释,
  3. 模板方法将始终返回字符串。

将代码从一种形式解析为另一种形式已经完成。现在我只需要一个方法来替代它。

“牛肉”示例:

  [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:

  1. Code can appear in any class.
  2. Template code will always be annotated with attribute [Template]
  3. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

农村范ル2024-09-04 04:00:43

请查看 T4(文本模板转换工具包)

<#@ template language="C#v3.5" #>
<#@ assembly name="System.Core" #>
<#@ output extension=".cs" encoding="utf-8" #>

private string GetSomething()
{
    <# Generate("Customer.Name"); #>
}

<#+
private void Generate(string s)
{
    WriteLine(@"MemoryStream mStream = new MemoryStream();");
    // ...
}
#>

Have a look at T4 (Text Template Transformation Toolkit).

<#@ template language="C#v3.5" #>
<#@ assembly name="System.Core" #>
<#@ output extension=".cs" encoding="utf-8" #>

private string GetSomething()
{
    <# Generate("Customer.Name"); #>
}

<#+
private void Generate(string s)
{
    WriteLine(@"MemoryStream mStream = new MemoryStream();");
    // ...
}
#>
轮廓§2024-09-04 04:00:43

DMS 软件再工程工具包及其C# 前端

DMS 解析您的文件,构建完整的抽象语法树,并允许您编写可以扩展文本中的点的自定义转换(大多数代码生成器(如 T4)所做的)或更重要的是替换任何构造(本地和/或分布在整个文本中)组成应用程序的文件集)以及您可能想要生成的任何其他代码。

您似乎对生成代码片段的元语言有一些了解,例如,

  From operation In metaObject.operations _ 
            Select (MethodTemplate.Create(operation).GetSourceCode) 

据我所知,该元语言不是 C#。使用 DMS,您可以为元语言定义解析器,并在代码生成器遇到构造时将元语言处理成树。通过此类树上的小型解释器,您可以将元语言文本转换为生成感兴趣文本的生成器操作。

[我是 DMS 背后的首席技术官]。

A tool that can parse C#, pick out attributes, and transform that code any way you'd like, is the DMS Software Reengineering Toolkit and its C# Front End.

DMS parses your files, builds full abstact syntax trees, and allows you to write custom transformations that can expand a point in the text (what most code generators like T4 do) or more importantly replace any construct (both local and/or distributed across the set of files that make up the application) with any other code you might like to generate.

You appear to have some idea about the metalanguage for producing code fragments, e.g.,

  From operation In metaObject.operations _ 
            Select (MethodTemplate.Create(operation).GetSourceCode) 

That metalanguage AFAIK isn't C#. With DMS, you can define a parser for the metalanguage, and process the meta langauge into trees as the code generator encounters the constructs. With a small interpreter over such trees, you can convert metalnguage text into generator actions producing the text of interest.

[I'm the CTO behind DMS].

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文