T4使用DTE打开生成的文件时,Visual Studio序列化错误

McG*_*V10 4 c# t4 envdte visual-studio-2015

我们有一个名为GenerateProxies.tt的C#T4文件,该文件调用了几个命令行代码生成实用程序。使用System.Diagnostics Process类,我们将标准输出重定向到T4输出文本文件(GenerateProxies.txt),以便我们可以查看命令行输出中的错误。

我在T4的末尾添加了以下简单代码,以便Visual Studio将打开生成的文本文件作为该过程的最后一步(该workingDirectory变量在模板的前面进行了声明和填充)。确实可以,但是会引发序列化错误。可以避免此错误吗?

<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#
    IServiceProvider vssp = (IServiceProvider)this.Host;
    DTE dte = vssp.GetService(typeof(DTE)) as DTE;
    dte.ItemOperations.OpenFile(
        string.Format(@"{0}\GenerateProxies.txt", workingDirectory),
        Constants.vsViewKindTextView
    );
#>
Run Code Online (Sandbox Code Playgroud)

再次,这确实起作用,它打开了文本文件,但是会产生此错误:

Running transformation: System.Runtime.Serialization.SerializationException:
Type 'Microsoft.VisualStudio.Platform.WindowManagement.DTE.WindowBase' in
Assembly 'Microsoft.VisualStudio.Platform.WindowManagement'
is not marked as serializable.
Run Code Online (Sandbox Code Playgroud)

Fak*_*int 8

EnvDTE程序集是COM互操作程序集。通过创建Runtime Callable Wrapper可以避免您的错误,该包装程序根据互操作程序集中的信息封送对COM对象的调用。Microsoft在Microsoft.VisualStudio.TextTemplating名称空间内提供了扩展方法 :

<#@ template hostspecific="true" language="C#" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#
  IServiceProvider serviceProvider = (IServiceProvider)this.Host;
  EnvDTE.DTE dte = (EnvDTE.DTE) serviceProvider.GetCOMService(typeof(EnvDTE.DTE));
 #>
Run Code Online (Sandbox Code Playgroud)

T4模板在单独的AppDomain中运行,并且我相信这是您的代码尽管存在异常却仍在工作的原因。IServiceProvider.GetService(typeof(DTE))返回一个透明的代理对象。此例外是因为代理要求跨应用程序域的对象必须用Serializable属性修饰。您可以确认代码中的DTE对象是“透明代理”,如下所示:

bool isProxy = RemotingServices.IsTransparentProxy(dte); 
Run Code Online (Sandbox Code Playgroud)

  • 开始获取错误“正在运行的转换:System.Runtime.Serialization.SerializationException”:在程序集“ Microsoft.VisualStudio.ProjectSystem.VS.Implementation,版本= 16.0”中键入“ Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.Automation.OAProjectItem” .0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a'在Visual Studio 2019中未标记为可序列化的T4模板,该模板在VS 2017中运行良好。如此处所述使用GetCOMService扩展方法对其进行更新即可修复它! (2认同)