开发者

T4 template generation error when trying to execute subsonic's activerecord in sharpdevelop

Hello,

I'm trying to get subsonic to work win SQLite in sharpdevelop (Active record approach).

I'm having some issues with generating the code from the T4 templates.

It throws this error: Blocks are not permitted after helpers - SQLiteTest.tt

If I remove the <#@ include file="SQLite.ttinclude" #> line it doesn't throw the error anymore, but of course it doesn't work.

The error must be somewhere in the SQLite.ttinclude or Settings.ttinclude I've looked through the ttinclude files but I have no idea what blocks or helpers 开发者_JS百科are.

Do you have any idea about what might be the cause of the error? Apparently mono develop T4 generator throws the same error but not Visual Studio's one.


It's a bit hard to say what they mean with Helper/Block as Visual Studio T4 refers the different segments as as Statement, Expression, BoilerPlate and ClassFeature IIRC.

While checking the source code for Mono T4 I would however guess that Block refers to Statements and Helpers refers to ClassFeatures.

T4 example:

<# // This is a Statement #>
<#+ // This is a ClassFeature #>

It's true that Statements can't appear below ClassFeatures in T4 but what I am thinking is happening here is that Visual Studio T4 does "smart" merging of ttinclude files. It's possible that Mono T4 doesn't.

To see why consider these two T4 files.

Example T4.ttinclude:

<# // 1. This is a Statement #>
<#+ // 1. This is a ClassFeature #>

Example T4.tt

<# // 2. This is a Statement #>
<#+ // 2. This is a ClassFeature #>
<#@ include file="T4.ttinclude" #>

A straightforward implementation of include would just merge the file:

<# // 2. This is a Statement #>
<#+ // 2. This is a ClassFeature #>
<# // 1. This is a Statement #>
<#+ // 1. This is a ClassFeature #>

But this is an illegal T4 template so what Visual Studio T4 does (to my knowledge) is merging the files into this which is legal:

<# // 1. This is a Statement #>
<# // 2. This is a Statement #>
<#+ // 1. This is a ClassFeature #>
<#+ // 2. This is a ClassFeature #>

So if I am allowed to make a guess is that Mono T4 includes file using the straightforward approach but the SubSonic templates are design for Visual Studio T4 which uses a slightly more refined include strategy.

If this is the reason you would need to

  1. Refactor SQLLite.ttinclude or Settings.ttinclude to only use ClassFeatures. That is probably a major refactoring as having Statements in a .ttinclude file is very convenient.
  2. Refactor Mono T4 to do something similar as Visual Studio T4

Neither is good news I fear.

PS. While reading the Mono code it seems the dev considered this:

//TODO: are blocks permitted after helpers?  
throw new ParserException ("Blocks are not permitted after helpers", seg.StartLocation);   


I ran into this problem as well, the solution however was simple.

  1. Move the <#@ include file="SQLServer.ttinclude" #> declaration to the end of each .tt file,. Luckily each ttinclude file only contains classFeatures

  2. you then need to refactor a few functions which rely on EvnDTE(which doesn't exist in mono). This is simple to do though, as these functions only return project paths. These functions are GetProjectPath, GetConfigPath, and GetDataDirectory. I just rewrote these to return Consts that are declared in the head of the file. Not as elegant as the auto-detection but simple enough to manage.

After doing those two things, i was able to successfully run the Subsonic T4 Templates.


This problem should now fixed in SharpDevelop 4.2. Class feature blocks that are added by including other T4 files are now supported. SharpDevelop also now exposes its own implementation of the Visual Studio object model from the T4 templating host. The Subsonic templates make use of the Visual Studio object model to determine the database connection string.

To get the Subsonic templates to work you need to make two modifications to the Settings.include file:

Replace the reference to the Visual Studio object model assembly (EnvDTE):

<#@ assembly name="EnvDTE" #>

With:

<#@ assembly name="$(addinpath:ICSharpCode.PackageManagement)PackageManagement.dll" #>

Add an import directive with a namespace alias for EnvDTE:

<#@ import namespace="EnvDTE = ICSharpCode.PackageManagement.EnvDTE" #>

Save these changes and then save the ActiveRecord.tt file to generate the database access code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜