Рефлексия, кодогенерация и обёртка - C#

Узнай цену своей работы

Формулировка задачи:

Доброго времени суток! Сначала прикладная задача: имеется статический класс, для которого необходимо делать не статическую обёртку. Руками сделать эту обёртку не приятно, но можно. Но проект живой, развивающийся и статический класс тоже, т.е. в нём время от времени появляются новые члены. А это значит что обёртку нужно постоянно актуализировать, что совсем уж ни в какие ворота. Я долго думал что с этим делать, рассматривал различные варианты и остановился на следующем: Custom Tool + кодогенерация. Мне кажется это будет идеальным решением. В конечном счёте обёртка всегда актуальная и для этого ничего не надо делать. Если я не прав и есть варианты по лучше, самое время мне сообщить об этом. Едем дальше. Нагуглил я статей про Custom Tool и примерно представляю как это работает, может быть по ходу ещё возникнут какие-то вопросы, но давайте пока считать этот вопрос решённым. Сейчас же у меня есть вопросы по реализации собственно кодогенератора. И так, опуская детали, Custom Tool принимает на вход файл, на основе которого мы будем генерить свой файл, обёртку для класса в моём случае. И тут я вижу два пути, простой и правильный. Простой. Добавляем в кодогенератор референс на мою сборку с оборачиваемым классом, игнорируем входной файл и просто генерим то что нам нужно через рефлексию. Но хочется сделать по правильному, а по правильному, это не завязываться на конкретную реализацию и сделать универсальный кодогенератор, который можно будет использовать и в будущем для других проектов. А это значит никаких референсов на проект и работать со входным файлом. Отсюда у меня вытекают 2 вопроса: 1. Можно ли как-то заюзать рефлексию имея лишь текстовый файл с классом? 2. Может быть есть какой-то удобный способ парсить cs файл? Мои навыки гугления не помогли, а парсить файл руками совсем не хочется. У простого способа есть ещё один недостаток, Custom Tool срабатывает когда изменяется файл к которому он привязан. А рефлексия подозреваю не увидит изменений в классе, пока он не будет скомпилирован. Мелочь, а не приятно.

Решение задачи: «Рефлексия, кодогенерация и обёртка»

textual
Листинг программы
  1. <#@ template debug="false" hostspecific="true" language="C#" #>
  2. <#@ assembly name="System.Core" #>
  3. <#@ import namespace="System.Linq" #>
  4. <#@ import namespace="System.Text" #>
  5. <#@ import namespace="System.Collections.Generic" #>
  6. <#@ output extension=".cs" #>
  7. <#@ assembly name="EnvDTE" #>
  8. <#@ import namespace="EnvDTE" #>
  9.  
  10. namespace Wrappers
  11. {
  12. <#
  13. string projectName = "t4generatewrapper";
  14. string[] classNames = {"t4generatewrapper.ClassToWrap"};
  15. IServiceProvider serviceProvider = (IServiceProvider) this.Host;
  16. EnvDTE.DTE dte = (EnvDTE.DTE) serviceProvider.GetService(typeof(EnvDTE.DTE));
  17. Project currentProject = null;
  18. foreach (Project p in dte.Solution.Projects)
  19. {
  20. if(p.Name == projectName)currentProject = p;
  21. }
  22.  
  23. foreach (string classFullName in classNames)
  24. {
  25. var classCode = currentProject.CodeModel.CodeTypeFromFullName(classFullName);
  26. #>
  27.  
  28. public class <#= classFullName.Split('.').Last() #>Wrapper
  29. {
  30.  
  31. <# foreach (CodeFunction cf in classCode.Members.OfType<CodeFunction>())
  32. {
  33. var pars = string.Join(", ", from CodeParameter p in cf.Parameters select p.Type.AsFullName + " " + p.Name);
  34. var args = string.Join(", ", from CodeParameter p in cf.Parameters select p.Name);
  35. if(cf.Type.AsFullName == "System.Void")
  36. {#>
  37. public void <#= cf.Name #> (<#= pars #>)
  38. {
  39. <#= classFullName + "." + cf.Name #>(<#= args #>);
  40. }
  41. <# }
  42. else{ #>
  43.  
  44. public <#= cf.Type.AsFullName #> <#= cf.Name #>(<#= pars #>)
  45. {
  46. return <#= classFullName + "." + cf.Name #>(<#= args #>);
  47. }
  48. <#}
  49. } #>
  50. }
  51. <#
  52. } #>
  53. }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

10   голосов , оценка 4 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы