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(); 

} 

Это не важно, какая технология используется. Я пробовал использовать метод PostMark, но не получил нигде (из-за отсутствия опыта работы с ним). Я также изучил структуру Linfu. Может кто-нибудь предложить другой подход или способ сделать это, я бы очень признателен. От этого зависит весь мой проект.

Предположения:

  1. код может появиться в любом классе.
  2. Код шаблона всегда будет аннотирован с атрибутом [Template]
  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)); 

     } 
+3

В чем смысл этого делать в первую очередь? –

+0

@Matti: Это не соответствует точке. Я не могу вдаваться в подробности, почему это необходимо. – epitka

+1

Ваш шаблон существенно сводится к 'return Customer.Name;', что делает использование шаблонов несколько глупым. Поэтому, спрашивая, нужны ли шаблоны вообще, является актуальным вопросом ИМО. – dtb

ответ

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

@dtb: T4 могут появляться в любой части тела любого класса? – epitka

+0

@epitka: Да. Вы создаете файл '.tt', который содержит ваш код C#, измененный с помощью директив' <#= ... #>' и/или '<# ... #>'. Затем '.tt' преобразуется в файл' .cs' с помощью специального инструмента * TextTemplatingFileGenerator * перед компиляцией. – dtb

+0

Итак, VS будет генерировать файл, а затем скомпилировать его, и мне нужно только развернуть .dll? – epitka

0

инструмент, который может разобрать C#, выбрать атрибуты, и трансформировать, что код так, как вы хотите, это DMS Software Reengineering Toolkit и его C# Front End.

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

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

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

Это МЕТАЯЗЫК AFAIK не C#. С помощью DMS вы можете определить парсер для метаязыка и обработать мета-язык в деревьях, поскольку генератор кода встречает конструкции. С помощью небольшого интерпретатора над такими деревьями вы можете преобразовать текст metalnguage в действия генератора, создавая текст, представляющий интерес.

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

+0

Спасибо, что нашли время ответить на вопрос. Я обязательно посмотрю на ваш инструмент. Вы правы, это не метаданные C# reflection, а обычная метамодель, которая нацелена на развитие модели. – epitka

Смежные вопросы