Closed Stamo-Gochev closed 4 years ago
@weshaggard seems this could be because of your change below?
commit a4364b283016758aff4d8ea162e6e8c550e2da6f Author: Wes Haggard Wes.Haggard@microsoft.com Date: Mon Oct 16 11:46:43 2017 -0700
Update SupportedFrameworks to netcoreapp2.1 for some packages
@danmosemsft I don't believe it is related to that commit. It most likely has to do with changes in the shared framework between 1.1 and 2.0
@Stamo-Gochev is is kind of hard to follow exactly what you are doing and what is compiled when. Could you setup a repo with some sample projects that demonstrate the issue you are hitting and I will take a look and help you figure out a solution.
@danmosemsft @weshaggard
I will be working on isolating the issue in a project that I can send as it is not open-sourced, but what I have found so far is that the problem is caused by the System.Reflection.TypeExtensions
assembly not being referenced when the compilation is done and thus the GetProperties
method is not available.
The references to the assemblies that are necessary for the compilation are obtained by the GetReferences
method below - the Class Library project uses the HostingEnvironment variable, which is passed to it from the ASP.NET Core web app:
public class MyLibrary {
//injected by the ASP.NET Core web app
private readonly IHostingEnvironment _environment;
...
public void Compile()
{
//assume a correct string definition of the class
var tree = CSharpSyntaxTree.ParseText(@"
using System;
public class MyClass
{
public static void Main()
{
var instance = new MyClass();
var props = System.Reflection.TypeExtensions.GetProperties(instance.GetType(), System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
}
}");
...
var compilation = CSharpCompilation.Create(assemblyName,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
syntaxTrees: new[] { tree },
references: GetReferences()
...
}
...
//get the avaialble references based on the HostingEnvironment variable
public IEnumerable<MetadataReference> GetReferences()
{
var references = new List<MetadataReference>();
var applicationAssembly = Assembly.Load(new AssemblyName(_environment.ApplicationName));
var context = DependencyContext.Load(applicationAssembly);
if (context != null)
{
for (var i = 0; i < context.CompileLibraries.Count; i++)
{
var library = context.CompileLibraries[i];
IEnumerable<string> referencePaths;
try
{
referencePaths = library.ResolveReferencePaths();
}
catch (InvalidOperationException e)
{
continue;
}
//add the references
references.AddRange(referencePaths...);
}
}
return references;
}
...
}
The above code works fine in ASP.NET Core 1.1 project and the full list of loaded assemblies can be found at: https://pastebin.com/LZuTXchM
The System.Reflection.TypeExtensions
assembly is loaded and thus the compilation is successful.
On the other hande, the same code fails when executed in ASP.NET Core 2.0 project: https://pastebin.com/64hCTBSe
The System.Reflection.TypeExtensions
assembly is not loaded. In addition, InvalidOperationException
s are caught for the following entries:
"Cannot find compilation library location for package 'Microsoft.Win32.Registry'"
"Cannot find compilation library location for package 'System.Data.SqlClient'"
"Cannot find compilation library location for package 'System.Runtime.CompilerServices.Unsafe'"
"Cannot find compilation library location for package 'System.Security.AccessControl'"
"Cannot find compilation library location for package 'System.Security.Cryptography.Xml'"
"Cannot find compilation library location for package 'System.Security.Principal.Windows'"
"Cannot find compilation library location for package 'Microsoft.NETCore.App'"
I assume the whole thing is dependent on what is exposed by the HostingEnvironment
variable in the above snippet:
var applicationAssembly = Assembly.Load(new AssemblyName(_environment.ApplicationName));
var context = DependencyContext.Load(applicationAssembly);
(context.CompileLibraries)
After the above observations, it looks like the issue is not connected to dotnet/corefx
responsibilities at all, so it should be closed, but should it be forwarded to somebody in the ASP.NET Core team? The sole purpose of this is for them to fix a potential breaking change (if it makes sense to be fixed as this might be expected due to deprecated/removed code intentionally) - the "workaround" is to get the "private" System.Private.CoreLib.dll
as mentioned in https://github.com/dotnet/roslyn/issues/16211#issuecomment-372998985 which fixes the problem in the ASP.NET Core 2.0 project. This seems like the proper alternative to:
references.Add(MetadataReference.CreateFromFile(typeof(object).Assembly.Location));
but for .NET Core.
@davidfowl @anurse any ideas why HostingEnvironment seems to not work here? Is there some difference between 1.1 and 2.0 that needs to be accounted for?
Reassigning as right now, the investigation actionability is in ASP.NET, not CoreFx.
This should be closed and forwarded to ASP.NET but I don't know which repo to do that in. Changing the milestone so it stops showing up a 2.1 ZBB blocker in CoreFx.
@davidfowl where should this move to
HostingEnvironment is at https://github.com/aspnet/Hosting.
Looks like this is a pretty stale issue, referencing .NET Core 2.0 which is end-of-life. Is this issue still occurring on a supported release of .NET Core (currently 2.1 or 3.1)?
This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. If it is closed, feel free to comment when you are able to provide the additional information and we will re-investigate.
See our Issue Management Policies for more information.
I am using a Class Library project, whose target frameworks are
net451
andnetstandard1.6
, which dynamically compiles a class in a way similar to the example here (a "standard" way to do the compilation):https://github.com/dotnet/roslyn/issues/16211#issuecomment-372998985
but inside a method in
MyClass
, I want to retrieve all public properties like this (the actual code is the string of this, which is passed toCSharpSyntaxTree.ParseText
:Now, the Class Library project is referenced by an ASP.NET Core web app (assume any third party app that I have no control over), which targets
netcore1.1
and asSystem.Reflection.TypeExtensions.GetProperties
is available, it is working as expected.However, targeting
netcore2.0
throws an error although it looks like the method should still be available. The alternative (used fornet451
above):is actually working for
netcore2.0
, but not fornetcore1.0
ornetcore1.1
. Also note that this happens only when compiling the class dynamically - using theMyClass
sPrint
method definition works OK in bothnetcore1.0
andnetcore2.0
without the dynamic compilation.Can you provide more information why this is happening and if it is required for the
netcore2.0
project to "provide" theSystem.Reflection.TypeExtensions
package?