VS2022 17.2.0 Preview 2.0: T4 template serialization exception when accessing projects, etc

Viewed 1966

Using VS2022 17.2.0 Preview 2.0 to generate data layer using T4 templates. Part of the T4 uses VS interop / DTE to access projects in solution.

The following T4 is a test:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="Microsoft.VisualStudio.Shell.Interop"#>
<#@ import namespace="Microsoft.VisualStudio.Shell"#>
<#@ import namespace="Microsoft.VisualStudio.Shell.Interop"#>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="EnvDTE80" #>
<#@ output extension=".txt" #>
<#

var hostServiceProvider = Host as IServiceProvider;
var dte = hostServiceProvider.GetService(typeof(DTE)) as DTE2;

foreach (Project project in dte.Solution)
{
    #><#= project.Name #>
    <#
}
#>

This produces following exception:

Error       Running transformation: System.Runtime.Serialization.SerializationException: Type 'Microsoft.VisualStudio.CommonIDE.Solutions.CMiscProject' in Assembly 'Microsoft.VisualStudio.CommonIDE, Version=17.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not marked as serializable.

Issue did not exist in Preview 1.0 or in VS2019.

I have had a look around and pulled in nuget package for Microsoft.VisualStudio.Interop, version 17.1.32210.191, but problem persists when accessing anything through the EnvDTE.DTE(2).

I know I'm jumping the gun on this as it is a preview version, but has anyone had this issue and solved it? Is there a different approach needed to access projects in the solution from the T4 template?

The error does not occur when debugging the T4 template.

1 Answers

I had a bit of a play (and a lot of a Google) and found the following solved it for me under VS 2022:

Ensure you have the following assemblies and namespaces

<#@ assembly name="Microsoft.VisualStudio.Interop" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="EnvDTE80" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>

and then swap out the IServiceProvider's GetService for GetCOMService

//var dte = hostServiceProvider.GetService(typeof(DTE)) as DTE2;
var dte = hostServiceProvider.GetCOMService(typeof(DTE)) as DTE2;

Mostly from answer here: https://stackoverflow.com/a/53346767/2797450

Related