我们有一个名为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.
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");
}
这不是答案,但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