1

这是我一段时间以来一直在努力解决的问题。我需要一种方法,要么在编译时用模板中的解析代码替换方法中的代码(想到 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));

        }
4

2 回答 2

2

看看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();");
    // ...
}
#>
于 2010-04-07T13:09:25.350 回答
0

DMS Software Reengineering Toolkit及其C# Front End是一个可以解析 C#、挑选属性和转换代码的工具。

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

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

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

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

[我是 DMS 背后的 CTO]。

于 2010-04-07T19:30:42.740 回答