Loading a NuGet assembly in T4 Template
Asked Answered
R

2

10

I need to reference a Type in one of the assemblies referenced by the project containing my Visual Studio T4 template. However, the referenced assembly is installed from a NuGet package. As that Nuget reference evolves, so will the path that NuGet places it in within my solution's packages folder. For example, suppose my NuGet package is:

  • Facade.Contract.1.0.1-alpha

Then the relative path to it from my project is:

  • ..\packages\Facade.Contract.1.0.1-alpha\lib\net4\Facade.Contract.dll

If the prerelease is updated to beta, that path will change. When the package is released, the path will change. And every time the path changes, the assembly line in my *.tt file is out of date:

  • <#@ assembly name="..\packages\Facade.Contract.1.0.1-alpha\lib\net4\Facade.Contract.dll" #>

I don't think there's a way to accomplish this directly with the assembly directive; however, I'm open to some crazy ideas. Could I load the assembly myself into the current, or a subordinate or reflection-only AppDomain?

I think I could, but I'm not sure how to go about dynamically discovering the path to the referenced assembly in the project's references using T4 logic.

Any ideas?

Ribbonwood answered 24/10, 2014 at 20:53 Comment(4)
how are you executing your T4 templates, are they run within Visual Studio or during build using msbuild?Dextrality
It's run inside Visual Studio (unlike what I said in my edit... I'll correct that as soon as possible). So I should have access to the whole DTE.Ribbonwood
I'm making a little progress using VSLangProj to discover reference paths, after being inspired by this article: t4-editor.tangible-engineering.com/blog/…Ribbonwood
Great question, and a big omission in T4 IMO. Please vote on UserVoice: visualstudio.uservoice.com/forums/121579-visual-studio-2015/….Bosk
R
4

I've found a solution using VSLangProject as suggested by this article: http://t4-editor.tangible-engineering.com/blog/add-references-to-visual-studio-project-from-t4-template.html

Given a string serviceContractReferenceAssembly a to identify the name of the reference assembly in my containing project, and serviceContractReferenceType to identify the type within that assembly, the following worked:

    var templateItem = dte.Solution.FindProjectItem(this.Host.TemplateFile);
    var project = templateItem.ContainingProject;
    var vsProject = project.Object as VSLangProj.VSProject;
    foreach(var referenceObj in vsProject.References)
    {
        var reference = (VSLangProj.Reference)referenceObj;
        if(reference.Name != serviceContractReferenceAssembly) continue;
        var serviceContractAssembly = Assembly.LoadFile(reference.Path);
        var serviceContractType = serviceContractAssembly.GetType(serviceContractReferenceType);
        // Do something with it here
    }
Ribbonwood answered 27/10, 2014 at 13:16 Comment(0)
D
2

The Nuget team has made an extension available that allows you some control over the packages in a solution/project. So if you have control over the environment and can be sure everyone has this installed you might be able to search for the installed packages and then dynamically load them during your T4 execution. Since these Nuget assemblies are already complied and not part of your solution/project I would think using the standard Assembly.Load would work but you would need to test that.

Dextrality answered 27/10, 2014 at 12:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.