Search code examples
nuget.net-assemblyt4

Loading a NuGet assembly in T4 Template


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?


Solution

  • 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
        }