为什么在T4模板中无法反映自己的类型?

时间:2018-10-07 11:46:05

标签: c# reflection .net-core t4 asp.net-core-2.1

我有一个.NET Core 2.1 ASP.NET MVC应用程序,其中有一个设计时T4模板,我想用它来生成一些代码。当前,它看起来像这样:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="$(SolutionDir)\Bar\bin\Debug\netcoreapp2.1\Bar.dll" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="Bar" #>
<#@ output extension=".txt" #>
<#
    var myType = typeof(string);
    var myName = y.Name;
    Write(myName);    
#>

这有效:该模板生成的.txt文件包含“字符串”。

但是,现在我在Foo.cs中有一个与模板相同的文件夹中的Foo类:

namespace Bar
{
    public class Foo
    {
    }
}

现在我要使用Foo而不是字符串,所以我只需要更改行

var myType = typeof(string);

var myType = typeof(Foo);

并保存模板。现在我得到一个错误:

  

正在运行的转换:System.IO.FileNotFoundException:无法   加载文件或程序集'System.Runtime,Version = 4.2.1.0,   文化=中性,PublicKeyToken = b03f5f7f11d50a3a'或其中之一   依赖性。

堆栈跟踪如下:

File name: 'System.Runtime, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
    at Microsoft.VisualStudio.TextTemplating9418B77BB4C607966DB4F31F6C9D57D97D9892B08324572567CEAC228ECCD2BE3839F9E2A0AE0ECA2D5DD0CCC161A70762C40A6D67A8DC505F3E88E86A36C7CE.GeneratedTextTransformation.TransformText()
    at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
    at CallSite.Target(Closure , CallSite , Object )   
    at Microsoft.VisualStudio.TextTemplating.TransformationRunner.PerformTransformation()

为什么会引发此错误?为什么反射对于内置字符串类型有效,但是以某种方式依赖于.NET Framework 4.2.1作为我自己的.NET Core 2.1类型?

2 个答案:

答案 0 :(得分:1)

T4引擎使用.NetFramework,因此与其他任何.Net Framework应用程序一样,引用.net核心dll的问题相同。 T4在单独的应用程序域中运行,并且不会继承.net核心项目的引用。

typeof(string)之所以有效,是因为它是.Net Framework的一部分。您的“ Foo”类型取决于对.Net Core程序集的引用。我不确定是否可以将.Net Core程序集加载到T4中,而无需将程序集移植到.Net Standard。

您可以尝试Loading The Assembly in a Reflection-Only Context,但是我看到人们使用T4的通常方法是通过EnvDTE,Roslyn或Visual Studio SDK访问他们在项目中拥有的类的信息。除非有其他原因要从T4反映到.Net核心程序集中,否则通过EnvDTE检索类型信息将毫无问题!

答案 1 :(得分:1)

我得到了解决方法。

尝试将此bindingRedirect放在C:\Users\<user>\AppData\Local\Microsoft\VisualStudio\15.0_29f8d23a\devenv.exe.config-> <configuration>-> <runtime>中的<assemblyBinding>里面,所有其他的bindingRedirect都在哪里

<dependentAssembly>
  <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
  <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="4.0.0.0"/>
</dependentAssembly>