Как перехватить, разобрать и скомпилировать? - PullRequest
1 голос
/ 07 апреля 2010

Это проблема, которую я долго пытался решить. Мне нужен способ заменить код в методе на анализируемый код из шаблона во время компиляции (на ум приходит 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. Код шаблона всегда будет аннотирован атрибутом [Шаблон]
  3. Метод шаблона всегда будет возвращать строку.

Разбор кода из одной формы в другую уже сделан. Теперь мне просто нужен способ заменить его.

Пример "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 ]

2 голосов
/ 07 апреля 2010

Взгляните на 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();");
    // ...
}
#>
0 голосов
/ 07 апреля 2010

Инструментом, который может анализировать C #, выбирать атрибуты и преобразовывать этот код любым удобным для вас способом, является набор средств реинжиниринга программного обеспечения DMS и его C # Front End .

DMS анализирует ваши файлы, создает полные деревья синтаксиса с абсолютным синтаксисом и позволяет вам писать собственные преобразования, которые могут расширить точку в тексте (что делает большинство генераторов кода, например, T4) или, что более важно, заменить любую конструкцию (как локальную, так и/ или распределены по ( файлам, составляющим приложение) с любым другим кодом, который вы можете сгенерировать.

Похоже, у вас есть некоторое представление о метаязыке для создания фрагментов кода,например,

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

Этот метаязык AFAIK не C #.С DMS вы можете определить синтаксический анализатор для метаязыка и обработать метаязык в деревья, когда генератор кода встречает конструкции.С помощью небольшого интерпретатора над такими деревьями вы можете конвертировать металический текст в действия генератора, создавая интересующий вас текст.

[Я технический директор DMS].

...