Мы сделали что-то похожее на это. Наше решение имеет следующие элементы:
- Пользовательский хост
- Пользовательский базовый класс шаблона (свойство «наследует» директивы шаблона)
- Шаблоны, специфичные для хоста (свойство hostspecific для директивы шаблона)
Пользовательский хост агрегируется объектом, для которого сам трафарет хочет вызывать методы.
interface ICallbackInterface
{
void CallbackFxn();
}
[Serializable]
public class MyCustomHost : ITextTemplatingEngineHost, ITextTemplatingSessionHost, IStencilFileRecordManagement
{
private ICallbackInterface callback = null;
public MyCustomHost(ICallbackInterface cb)
{
callback = cb;
}
public void CallbackFxn()
{
callback.CallbackFxn();
}
}
public abstract class MyTemplateBase : TextTransformation
{
public virtual MyCustomHost CustomHost
{
get
{
dynamic metame = this;
MyCustomHost rval = null;
try
{
/// <summary>
/// The "Host" property will be added to the generated class by the T4 environment whenever a
/// "hostspecific" template is processed.
/// </summary>
rval = metame.Host as MyCustomHost;
}
catch (RuntimeBinderException e)
{
logger.ErrorException(
"Received the following exception while processing a stencil template", e);
}
return rval;
}
}
}
Теперь в любом из наших шаблонов мы можем вызывать методы для объекта, которые фактически начали обработку, используя пользовательское свойство хоста, например:
<# CustomHost.CallbackFxn(); #>
Кроме того, мы не используем T4 в VS или отдельный исполняемый файл - мы ссылаемся на сборки Microsoft.VisualStudio.TextTemplating.10.0 и Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.
EDIT
Мы используем шаблоны T4, позволяющие пользователям определять свои собственные плагины для использования на определенном этапе нашего рабочего процесса продукта. Пользовательские шаблоны загружаются в нашу систему и обрабатываются так:
using Microsoft.VisualStudio.TextTemplating;
class UserPluginWorkflowComponent : ICallbackInterface
{
public void CallbackFxn()
{
// invoked by user plugin
}
public void ExecuteUserPlugin()
{
MyCustomHost host = new MyCustomHost(this);
host.TemplateFileValue = "UserPluginTemplateFilename";
Engine engine = new Engine();
string pluginResult = engine.ProcessTemplate(
userPluginTemplateFileContents,
host);
if (!host.Errors.HasErrors)
{
// use pluginResult in some meaningful way
}
}
}