32

I have the following code in a tester class in my main assembly, PocoGenerator. This assembly is supposed to use a T4 template to generate POCO's based on L2S entities in a referenced assembly (a project reference), DataObjects.

var assemblyName = "DataObjects";
var dataObjects = AppDomain.CurrentDomain.Load(new AssemblyName(assemblyName));

Try as I may, I cannot get T4 to find the DataObjects assembly. I have tried various forms of assembly directives, like:

<#@ assembly name="DataObjects" #>
<#@ assembly name="DataObjects, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" #>

to no avail. The code above works in the tester class, but not in the template. What am I doing wrong?

ADDED: I have resolved this issue by using the absolute path to the assembly in bot places I reference it, the directive as well as the class feature block, i.e.

<#@ assembly name="C:\Development\PocoGenerator\DataObjects\bin\Debug\DataObjects.dll" #>

and

var sourceAssembly = Assembly.LoadFile(@"C:\Development\PocoGenerator\DataObjects\bin\Debug\DataObjects.dll");

But I really don't like this, as I would like to use this template in various projects, and I just plain hate duplication, especially of magic strings.

ProfK
  • 49,207
  • 121
  • 399
  • 775
  • Your template project should have a project reference to the project you have a dependency on. Your "assembly" tag above looks right. And you should also have an "import" reference as well. What exact error message are you getting? (and what's with the AppDomain stuff? you shouldn't have to do anything like that) – Kirk Woll Aug 08 '10 at 16:58
  • The AppDomain stuff is tp enable me to iterate all the types in one of the assemblies loaded in the current AppDomain. It has nothing to do with referencing the assembly for the template itself. – ProfK Aug 08 '10 at 17:22
  • Yes, I see now. And what exact error message are you receiving? – Kirk Woll Aug 08 '10 at 18:54
  • 1
    @Kirk, please see my latest edit. – ProfK Aug 09 '10 at 08:46

4 Answers4

54
<#@ assembly name="$(ProjectDir)bin\Debug\ProofOfConcept.dll" #>

Happy Coding!

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Eric
  • 556
  • 5
  • 3
  • 1
    Although note this is a VS2010-only feature – GarethJ Jan 15 '11 at 22:30
  • 30
    Or even better: `<#@ assembly name="$(ProjectDir)$(OutDir)$(TargetFileName)" #>` – Jürgen Steinblock Feb 08 '11 at 10:34
  • 13
    Simplest: `<#@ Assembly name="$(TargetPath)" #>` – pylover Jul 21 '12 at 08:16
  • 5
    Isn't this only applicable if the project has already been built? I want to be able to use a referenced assembly to generate code before the project is built. – Sean Glover Oct 08 '13 at 00:08
  • 1
    I found a solution that works well in my usecase. Create another project in your solution with the same references (that can be updated enmasse with NuGet), update the build order, configure its build output to somewhere deterministic (i.e. $(SolutionDir)\..\MyT4Assemblies), and make whatever project with your T4 template dependent on it being build first. http://stackoverflow.com/a/9354103/895309 – Sean Glover Oct 08 '13 at 00:57
  • @Garethj, what am i gonna do with vs2013? – machinarium Jun 11 '15 at 07:40
  • Sorry @machinarium, don't understand your comment. – GarethJ Jul 14 '15 at 01:08
15

To reference assembly in T4 template in VS2010 you have some options:

  1. GAC your assemblies and use Namespace Reference or Fully Qualified Type Name
  2. Use a hard-coded Fully Qualified UNC path
  3. Copy assembly to Visual Studio "Public Assemblies Folder" and use Namespace Reference or Fully Qualified Type Name.
  4. Use or Define a Windows Environment Variable to build a Fully Qualified UNC path.
  5. Use a Visual Studio Macro to build a Fully Qualified UNC path.

I would suggest that you put a referenced assembly in your Public Assemblies Folder, another, maybe even better solution would be to hard code the path of your referenced assemblies.

Very nice post on this topic: T4 Template error - Assembly Directive cannot locate referenced assembly in Visual Studio 2010 project.

Basically MS decided to the the braking change, that the project referenced assemblies are not referenced by T4 engine, too.

T4's assembly set is completely separated from the containing project's assembly set to avoid picking up the wrong assemblies when a project targets previous framework versions. Project assemblies are no longer used to resolve template assembly directives.

More on that: What's new in T4 in Visual Studio 2010

Peter Stegnar
  • 12,615
  • 12
  • 62
  • 80
  • +1 for the project reference not being used any more, that was killing me! – dbones Oct 09 '12 at 18:09
  • @Peter Stegnar I ask a related question here: http://stackoverflow.com/questions/13838142/put-all-methods-in-one-tt-file-and-use-it-in-another-t4-files-in-codetemplates would you please check it – Saeid Dec 12 '12 at 11:20
1

I had a similar problem when I tried to include Less Css for .NET in my Web project.

I've ended up with copying the assembly in the root folder of my project and including it as a reference in the project itself. Then, I've added the following lines in the .tt file:

<#@ assembly name="dotless.Core.dll" #>

<#@ import namespace="dotless.Core" #>
<#@ import namespace="dotless.Core.configuration" #>

I'm sure that something similar should work with your assembly as well...

David
  • 8,340
  • 7
  • 49
  • 71
Regent
  • 5,502
  • 3
  • 33
  • 59
0

I've found there are a number of cases in creating and using the gax toolkit and packages where the build is perfectly happy with the way references are structured but the runtime gets all bothered because it can't find what it's looking for - this usually occurs when the main assembly references an assembly that uses gax elements and then that assembly in turn references another assembly that the main does not.

try directly including the assembly in question in your main assembly - and consider that you may need to write post build instructions to move it to an 'expected' location - while a nusiance, it should beat having to hardwire the path.

YMMV

Mark Mullin
  • 1,340
  • 1
  • 9
  • 21