Как вы используете .net Reflection с T4?

У меня есть проект С#, который включает текстовый шаблон. Я хотел бы, чтобы этот шаблон генерировал некоторый SQL на основе отражения классов С# в проекте.

Как получить доступ к содержимому текущего проекта с помощью T4? Возможно ли это, и если да, то доступен ли Reflection, или это доступ только к необработанному источнику, который затем должен быть проанализирован?

Заранее спасибо!


person Andrew Theken    schedule 06.12.2009    source источник
comment
Дубликат stackoverflow. ком/вопросы/1153542/?   -  person Paolo Tedesco    schedule 07.12.2009


Ответы (3)


Как получить доступ к содержимому текущего проекта с помощью T4?

Одним из способов является использование COM-компонента EnvDTE. Поиск в Google T4 и EnvDTE должен дать множество примеров.

Возможно ли это, и если да, то доступен ли Reflection, или это доступ только к необработанному источнику, который затем должен быть проанализирован?

Отражение точно доступно с Т4. Он работает в основном так, как вы ожидаете.

У Олега Сыча есть несколько замечательных записей в блогах, посвященных распространенным сценариям использования T4, но существует множество других ресурсов для T4. там тоже.

person Michael Maddox    schedule 23.12.2009
comment
Отражение обычно считается плохим методом через T4, потому что оно блокирует файлы или сборку, поэтому вы не можете их редактировать, EnvDTE COM не имеет этого ограничения. - person Maslow; 08.04.2010
comment
@Maslow: каждый раз, когда вы каким-либо образом получаете доступ к DLL из T4 внутри Visual Studio (рефлексия или нет), DLL блокируется и не может быть легко изменена без закрытия Visual Studio и повторного открытия. Я лично считаю, что это ошибка в реализации Visual Studio T4 (Microsoft, скорее всего, скажет, что это функция кэширования). Блокировка происходит и с EnvDTE, но вы не пытаетесь изменить эту DLL, поэтому не замечаете, что она заблокирована, и это не имеет значения. Эта проблема с блокировкой не имеет ничего общего с отражением, она возникает, даже если вы не используете отражение. - person Michael Maddox; 08.04.2010
comment
@Michael - Олег Синк специально говорит не использовать отражение внутри T4 stackoverflow.com/questions/1153542/ Я не знаю причин, и, возможно, контекст там был другим, но это то, что я добавлял в эту ветку, я должен нашел ссылку и включил ее в первоначальный комментарий. - person Maslow; 08.04.2010
comment
@Maslow: я знаю об этом сообщении Олега (давно я проголосовал за комментарий orsogufo выше), и я думаю, что теперь понимаю, что вы пытаетесь сообщить. Да, для сценария в этом вопросе есть лучшие варианты, чем отражение, которое не блокирует библиотеки DLL. Вызов метода в DLL — это то, что приводит к блокировке DLL, и есть способы проверить DLL без вызова методов. Спасибо. - person Michael Maddox; 08.04.2010
comment
@Maslow: T4 блокирует сборки в памяти. Представьте, что у вас есть шаблон, в котором вы берете свою недавно созданную dll и начинаете анализировать ее. В следующий раз, когда вы попытаетесь выполнить сборку, произойдет сбой, поскольку файл заблокирован и не может быть перезаписан. К счастью, это поведение меняется в SP1, поэтому отражение будет в порядке в шаблонах T4. - person ; 07.03.2011
comment
Отражение становится жизнеспособным в Vs2010 SP1. - person Maslow; 08.03.2011
comment
Отражение в T4 было специально рассмотрено blogs.msdn.com/b/t4/archive/2011/03/25/ - person Dave Swersky; 27.08.2012

Помимо проблем с блокировкой, будьте осторожны при использовании отражения в шаблоне T4. Генератор шаблонов в VS2010 работает с версией 4.0 Framework, поэтому вы можете ввести нежелательные зависимости, если создаете код для версии 3.5 или ниже.

Я только что обнаружил это на собственном горьком опыте, после использования отражения, чтобы решить, генерировать ли безпараметрические или параметризованные вызовы ToString для различных типов BCL. TimeSpan имеет только ToString() в 2.0, но 4.0 добавляет ToString(string) :P

person anton.burger    schedule 06.06.2011

Хотя это не решает проблемы с блокировкой (хотя я слышал, что VS2010 решает), вы можете попробовать скопировать dll во временное место и просто использовать эту скопированную сборку.

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".txt" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.IO" #>
<#    
var newFileName = System.IO.Path.GetTempFileName();
System.IO.File.Copy(@"C:\Development\CustomAssembly.dll",newFileName,true);

var assembly = Assembly.LoadFrom(newFileName);
var type = assembly.GetType("CustomAssembly.DummyClass");   
#>
<#=newFileName#>
<#=type#>
person Rob    schedule 16.05.2011
comment
Да, это позволяет избежать блокировки исходного файла, но AppDomain загружает сборку один раз и больше не загружает ее (независимо от имени файла). Мне не удалось загрузить файл в новый домен приложения, чтобы выгрузить его снова после завершения. - person Jason Kleban; 08.04.2012
comment
Загрузить сборку в виде массива байтов, используя базовый поток - person sll; 21.07.2013