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

问题描述 投票:3回答:2

我们有一个名为GenerateProxies.tt的C#T4文件,它调用了几个命令行codegen实用程序。使用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
    );
#>

同样,这确实有效,它打开文本文件,但它会生成此错误:

Running transformation: System.Runtime.Serialization.SerializationException:
Type 'Microsoft.VisualStudio.Platform.WindowManagement.DTE.WindowBase' in
Assembly 'Microsoft.VisualStudio.Platform.WindowManagement'
is not marked as serializable.
c# visual-studio-2015 t4 envdte
2个回答
4
投票

EnvDTE组件是COM互操作组件。通过创建Runtime Callable Wrapper可以避免您的错误,Microsoft.VisualStudio.TextTemplating根据interop-assembly中的信息封送对COM对象的调用。 Microsoft在<#@ 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)); #> 名称空间中提供了一个扩展方法:

IServiceProvider.GetService(typeof(DTE))

T4模板在一个单独的AppDomain中运行,我相信这是你的代码工作的原因,尽管例外。 Proxy Object返回透明的Serializable。此异常是因为代理需要使用bool isProxy = RemotingServices.IsTransparentProxy(dte); 属性修饰跨越app域的对象。您可以确认代码中的DTE对象是“透明代理”,如下所示:

private void WriteToOutput(string output)
{
      if (_host == null)
        throw new Exception("Host property returned unexpected value (null)");

      EnvDTE.DTE dte = (EnvDTE.DTE)_host.GetService(typeof(EnvDTE.DTE));

      if (dte == null)
        throw new Exception("Unable to retrieve DTE");

      Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
      window.Activate();

      var outputWindow = (EnvDTE.OutputWindow) window.Object;
      outputWindow.ActivePane.Activate();

      outputWindow.ActivePane.OutputString(output);
      outputWindow.ActivePane.OutputString("\n");
    }

2
投票

这不是答案,但OP无法按照评论中的要求提供堆栈跟踪。

当我尝试在我的tt文件中执行一个函数来写入Output窗口时,我会抛出一个类似的异常(ST太长,无法发表评论)

qazxswpoi

严重级代码描述项目文件行抑制状态错误运行转换:System.Runtime.Serialization.SerializationException:在程序集'Microsoft.VisualStudio.Platform.WindowManagement,Version = 15.0.0.0中键入'Microsoft.VisualStudio.Platform.WindowManagement.DTE.Windows' ,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a'未标记为可序列化。

服务器堆栈跟踪:位于System.Runtime.Serialization.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo的System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type,StreamingContext context)中的System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType类型)处于System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo的System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj,ISurrogateSelector surrogateSelector,StreamingContext context,SerObjectInfoInit serObjectInfoInit,IFormatterConverter converter,ObjectWriter objectWriter,SerializationBinder binder)。在System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize中序列化(Object obj,ISurrogateSelector surrogateSelector,StreamingContext上下文,SerObjectInfoInit serObjectInfoInit,IFormatterConverter转换器,ObjectWriter objectWriter,SerializationBinder binder)(Object graph,Header [] inHeaders,__BinaryWriter serWriter,B oolean fCheck) 在System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream,Object graph,Header [] headers,Boolean fCheck) 在System.Runtime.Remoting.Channels.CrossAppDomainSerializer.SerializeMessageParts(ArrayList的argsToSerialize)在System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage..ctor(IMethodReturnMessage MRM)在System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage.SmuggleIfPossible(即时聊天MSG)在System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(Object [] args)中的System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(Byte [] reqStmBuff,SmuggledMethodCallMessage smuggledMcm,SmuggledMethodReturnMessage&smuggledMrm)

在[0]处重新抛出异常:位于EnvDTE._DTE的System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&msgData,Int32类型)的System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg)。 get_Windows()在Microsoft.VisualStudio.TextTemplating8CBB5A87F4A34D52835396F51C533E1D8E9F22BC6977A9510B46C012D01E08C8AD263AC5BA030600D92BC0F39E7F1C3B6AA67D8CE545627E10A7F993E06C0D02.GeneratedTextTransformation.TypeMapper.WriteToOutput(字符串输出)在C:\的ViewModels \ BaseGridViewModels \ BaseViewModels.tt:线581在Microsoft.VisualStudio.TextTemplating8CBB5A87F4A34D52835396F51C533E1D8E9F22BC6977A9510B46C012D01E08C8AD263AC5BA030600D92BC0F39E7F1C3B6AA67D8CE545627E10A7F993E06C0D02.GeneratedTextTransformation.TypeMapper.GetItemsToGenerate [T](IEnumerable的在C:\ ViewModels \ BaseGridViewModels \ BaseViewModels.tt中的`1 itemCollection:在Microsoft.VisualStudio.TextTemplating8CBB5A87F4A34D52835396F51C533E1D8E9F22BC6977A9510B46C012D01E08C8AD263AC5BA030600D92BC0F39的第566行E7F1C3B6AA67D8CE545627E10A99F993E06C0D02.GeneratedTextTransformation.TransformText()在C:\ ViewModels \ BaseGridViewModels \ BaseViewModels.tt:第33行C:\ ViewModels \ BaseGridViewModels \ BaseViewModels.tt 581

© www.soinside.com 2019 - 2024. All rights reserved.