T4 使用 DTE 打开生成的文件时 Visual Studio 序列化错误 [英] Visual Studio serialization error when T4 uses DTE to open generated file

查看:33
本文介绍了T4 使用 DTE 打开生成的文件时 Visual Studio 序列化错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We have a C# T4 file named GenerateProxies.tt which calls several command-line codegen utilities. Using the System.Diagnostics Process class, we redirect the standard output to the T4 output text file (GenerateProxies.txt) so that we can review the command-line output for errors.

我在 T4 的末尾添加了以下简单代码,以便 Visual Studio 将打开生成的文本文件作为流程的最后一步(workingDirectory 变量在模板).这确实有效,但会引发序列化错误.这个错误可以避免吗?

I added the following simple code to the end of the T4 so that Visual Studio will open the generated text file as the last step in the process (the workingDirectory variable is declared and populated earlier in the template). This does work but it throws a serialization error. Can this error be avoided?

<#@ 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
    );
#>

同样,这个确实工作,它打开文本文件,但它产生这个错误:

Again, this does work, it opens the text file, but it generates this error:

Running transformation: System.Runtime.Serialization.SerializationException:
Type 'Microsoft.VisualStudio.Platform.WindowManagement.DTE.WindowBase' in
Assembly 'Microsoft.VisualStudio.Platform.WindowManagement'
is not marked as serializable.

推荐答案

EnvDTE 程序集是 COM 互操作程序集.通过创建 运行时可调用包装器,它根据互操作程序集中的信息封送对 COM 对象的调用.微软提供了一个扩展方法Microsoft.VisualStudio.TextTemplating 命名空间:

The EnvDTE assemblies are COM interop assemblies. Your error can be avoided by creating a Runtime Callable Wrapper, which marshals calls to the COM object based off information in the interop-assembly. Microsoft has provided an extension method within the Microsoft.VisualStudio.TextTemplating namespace:

<#@ 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));
 #>

T4 模板在单独的 AppDomain 中运行,我相信这就是您的代码在异常情况下仍能正常工作的原因.IServiceProvider.GetService(typeof(DTE)) 返回一个透明的 代理对象.此异常是因为代理要求使用 Serializable 属性修饰跨应用程序域的对象.您可以确认代码中的 DTE 对象是这样的透明代理":

T4 templates run in a separate AppDomain, and I believe that is the reason your code is working despite the exception. IServiceProvider.GetService(typeof(DTE)) returns a transparent Proxy Object. This exception is because the proxy requires objects crossing an app domain be decorated with the Serializable attribute. You can confirm the DTE object in your code is a "transparent proxy" like this:

bool isProxy = RemotingServices.IsTransparentProxy(dte); 

这篇关于T4 使用 DTE 打开生成的文件时 Visual Studio 序列化错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆