如何拦截,解析和编译?

时间:2010-04-07 12:49:34

标签: c# compiler-construction postsharp castle-dynamicproxy linfu-dynamicproxy

这是我一直在努力解决的问题。我需要一种方法来在编译时用模板中的解析代码替换方法中的代码(想到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,却没有任何进展(由于缺乏经验)。我也研究了林福框架。有人可以建议其他方法或方法来做到这一点,我真的很感激。我的整个项目取决于此。

假设:

  1. 代码可以出现在任何类中。
  2. 模板代码将始终使用属性[Template]
  3. 进行注释
  4. 模板方法将始终返回字符串。
  5. 已经完成了从一种形式到另一种形式的代码解析。现在我只需要一种方法来替换它。

    “Beefer”示例:

      [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));
    
            }
    

2 个答案:

答案 0 :(得分:2)

查看 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();");
    // ...
}
#>

答案 1 :(得分:0)

可以解析C#,挑选属性并以您想要的任何方式转换代码的工具是DMS Software Reengineering Toolkit及其C# Front End

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

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

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

那个元语言AFAIK不是C#。使用DMS,您可以为元语言定义解析器,并在代码生成器遇到构造时将元语言处理为树。通过对这些树的小型解释器,您可以将metalnguage文本转换为生成感兴趣文本的生成器操作。

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