T4 Template Could not load file or assembly 'System.Runtime, Version = 4.2.0.0'
Asked Answered
S

1

9

So I have a T4 Template I'm trying to run at design-time, but it keeps giving me the following error.

Running transformation: System.IO.FileNotFoundException: Could not load 
file or assembly 'System.Runtime, Version=4.2.0.0, Culture=neutral, 
PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system 
cannot find the file specified.
File name: 'System.Runtime, Version=4.2.0.0, Culture=neutral, 
PublicKeyToken=b03f5f7f11d50a3a'

My Visual Studios solution has 10 projects contained within it, all of which target .Net Core 2.0 framework. My T4 template presently looks as such:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="Services.Resources.DataTransferObjects.Infrastructures" #>
<#@ import namespace="System.Collections.Generic" #> 
<#@ assembly name="$(TargetDir)Services.dll" #>


<#@ output extension=".cs" #>
public class AdminDTO
{
        <#var editableObjs = Assembly
            .GetAssembly(typeof(GenericEditable<>))
            .GetTypes()
            .Where(p => p.BaseType != null && p.BaseType.IsGenericType && p.BaseType.GetGenericTypeDefinition() == (typeof(GenericEditable<>)))
            .ToList();
        #>
}

At the moment I only need the assembly I've referenced in the template, which is a .Net Core 2.0 class library project. I've tried adding the System.Runtime.dll reference in this particular library, but it doesn't appear to make any difference.

I've read several other issues similar to this, and it generally seems that .Net Core seems to have issues with T4 Templates, but it appeared most peoples' solutions were to target a .Net Standard library. I'm not sure this is applicable for me, as my entire solution only involves .Net Core projects.

EDIT

I changed all my projects to target .Net Standard 2.0 instead of .Net Core, and that fixed my initial problem, but now I see this error:

System.Reflection.ReflectionTypeLoadException: Unable to load one or 
more of the requested types. Retrieve the LoaderExceptions property for 
more information.
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.RuntimeModule.GetTypes()
at System.Reflection.Assembly.GetTypes()
Simmers answered 27/7, 2018 at 3:17 Comment(8)
You can reference a netstandard project from a core project.Territoriality
Well none of mine are netstandard. So I could go through the effort of making them such, but I don't see why there wouldn't be a proper netcore solution eitherSimmers
Agreed there should be a way but converting projects isn't hard or time consumingTerritoriality
If it comes to that I may go down that path. Technically only 1 of my projects 'needs' to be a netcore projectSimmers
If that's the case you would gain portability as a side effect. Might well be worth it. They should fix that issue in the framework though...Territoriality
Looks like migrating might not be possible. I really don't like .Net Core's version of Entity Framework, so if I transition back to .net framework (not .net standard) I would rather use EF6, but I guess .Net Core can only reference either .Net Core or .Net Standard, neither of which are compatible with EF6Simmers
EF 6 will be ported to Core in 3.0Territoriality
Changing all my frameworks to netstandard2.0 removed the Runtime exception, but introduced a new one. I think its a step in the right direction thoughSimmers
H
17

I found a workaround for the System.Runtime dll error.

Put this bindingRedirect inside the C:\Users\<user>\AppData\Local\Microsoft\VisualStudio\15.0_29f8d23a\devenv.exe.config inside <configuration> -> <runtime> -> <assemblyBinding> where are all the others bindingRedirect's

<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>

It's a bug in Visual Studio or T4 Template Engine: https://developercommunity.visualstudio.com/content/problem/358905/filenotfoundexception-systemruntime-version4210-wh.html

Hermetic answered 22/1, 2019 at 18:58 Comment(8)
Thanks so much! I can't believe I saw this answer just now. Tried it out recently and it did fix my issue. I recently got Visual Studios 2019 so I was hoping they would've fixed it then. Hopefully with .Net Core 3.0 it'll work as-is.Simmers
Quick update...they didn't fix it for .Net Core 3.0Simmers
This worked for me but I am stuck with a System.Collections one that is very similar... Thoughts?Yeast
Is there a generic solution for multipeople project? meaning, there's 200+ people in my team who would be interacting with the same c# .sln, and having them modify their devenv config is not a scalable solution. Is this something that could be configured say, in an app.config file?Buprestid
@Yeast I found that repeating the 4 lines shown, replacing System.Runtime with System.Collections or whichever assembly the message said was missingGroschen
For VS2022 Net6.0, this didn't work for me. However. I have the liberty of owning the source to a DLL I'm trying to consume. I backed the consumed DLL project down to a .Net framework 4.8. Compile the consumed project. And now my T4 can load my DLL and use the contents.Aholah
For VS2022 .Net 6.0, I found a working solution/workaround here: https://mcmap.net/q/1172654/-using-net-core-assemblies-in-t4-templates. It involves an extension that needs to be installed into VS that works around the bugged part of T4. Source on GitHub.Velasco
For VS2022 .Net6.0,I use<dependentAssembly> <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="4.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Collections" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="4.0.0.0"/> </dependentAssembly>So for any newer .Net version just replace oldVersion="0.0.0.0-x.0.0.0"('x' is your version)Harlequinade

© 2022 - 2024 — McMap. All rights reserved.