Fix #12 - Give base-path the lowest precedence when searching for managed libraries

This fixes assembly loading for System.Drawing.Common. This package was a rare case of a package with both runtime agnostic and runtime-specific versions of the managed library. This means the .NET Core SDK will dump System.Drawing.Common.dll in the plugin base path *as well as* a version in the runtimes/ folder. In this case, corehost actually treats the runtime specific asset with higher priority.

This change updates the ManagedLoadContext to imitate this behavior.
This commit is contained in:
Nate McMaster 2018-10-20 16:49:00 -07:00
parent b966dd75ad
commit fad7d2f5a4
No known key found for this signature in database
GPG Key ID: 157F9066DEF38BD0
10 changed files with 87 additions and 15 deletions

View File

@ -1,4 +1,4 @@
version: 0.2.0.{build}
version: 0.2.1.{build}
build_script:
- ps: .\build.ps1 -ci
environment:

11
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}

View File

@ -26,7 +26,7 @@
<NoWarn>$(NoWarn);NU5105</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateFullPaths Condition="'$(VSCODE_PID)' != ''">true</GenerateFullPaths>
<GenerateFullPaths Condition="'$(VSCODE_CWD)' != ''">true</GenerateFullPaths>
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory).build\obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath>
<BaseOutputPath>$(MSBuildThisFileDirectory).build\bin\$(MSBuildProjectName)\</BaseOutputPath>
</PropertyGroup>

View File

@ -57,6 +57,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plátano", "test\TestProjects\Plátano\Plátano.csproj", "{5889B0C9-50E5-4FDC-933B-8684B9FAB8E4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DrawingApp", "test\TestProjects\DrawingApp\DrawingApp.csproj", "{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -247,6 +249,18 @@ Global
{5889B0C9-50E5-4FDC-933B-8684B9FAB8E4}.Release|x64.Build.0 = Release|Any CPU
{5889B0C9-50E5-4FDC-933B-8684B9FAB8E4}.Release|x86.ActiveCfg = Release|Any CPU
{5889B0C9-50E5-4FDC-933B-8684B9FAB8E4}.Release|x86.Build.0 = Release|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Debug|x64.ActiveCfg = Debug|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Debug|x64.Build.0 = Debug|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Debug|x86.ActiveCfg = Debug|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Debug|x86.Build.0 = Debug|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Release|Any CPU.Build.0 = Release|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Release|x64.ActiveCfg = Release|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Release|x64.Build.0 = Release|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Release|x86.ActiveCfg = Release|Any CPU
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -268,6 +282,7 @@ Global
{78D2B20D-B173-4CF2-A763-F2AA5347947E} = {98E964A2-55DA-4740-9F2E-B64FDF6715DB}
{C0BA460C-C1AC-4C54-9C88-60E4B8681E94} = {98E964A2-55DA-4740-9F2E-B64FDF6715DB}
{5889B0C9-50E5-4FDC-933B-8684B9FAB8E4} = {98E964A2-55DA-4740-9F2E-B64FDF6715DB}
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB} = {98E964A2-55DA-4740-9F2E-B64FDF6715DB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B1AF41DC-A03E-47B1-BBDB-3DC27ABD9F74}

View File

@ -1,5 +1,11 @@
<Project>
<PropertyGroup>
<PackageReleaseNotes Condition="'$(VersionPrefix)' == '0.2.1'">
<![CDATA[
Bug fix:
* Fix a bug in the loader which causes System.Drawing.Common to load incorrectly. This one is super
]]>
</PackageReleaseNotes>
<PackageReleaseNotes Condition="'$(VersionPrefix)' == '0.2.0'">
<![CDATA[
Enhancements:

View File

@ -126,18 +126,7 @@ namespace McMaster.NETCore.Plugins.Loader
private bool SearchForLibrary(ManagedLibrary library, out string path)
{
// 1. Search in base path
foreach (var ext in PlatformInformation.ManagedAssemblyExtensions)
{
var local = Path.Combine(_basePath, library.Name.Name + ext);
if (File.Exists(local))
{
path = local;
return true;
}
}
// 2. Check for in _basePath + app local path
// 1. Check for in _basePath + app local path
var localFile = Path.Combine(_basePath, library.AppLocalPath);
if (File.Exists(localFile))
{
@ -156,6 +145,17 @@ namespace McMaster.NETCore.Plugins.Loader
}
}
// 3. Search in base path
foreach (var ext in PlatformInformation.ManagedAssemblyExtensions)
{
var local = Path.Combine(_basePath, library.Name.Name + ext);
if (File.Exists(local))
{
path = local;
return true;
}
}
path = null;
return false;
}

View File

@ -49,6 +49,23 @@ namespace McMaster.NETCore.Plugins.Tests
Assert.Equal("Red", method.Invoke(Activator.CreateInstance(type), Array.Empty<object>()));
}
[Fact]
public void ItPrefersRuntimeSpecificManagedAssetsOverRidlessOnes()
{
// System.Drawing.Common is an example of a package which has both rid-specific and ridless versions
// The package has lib/netstandard2.0/System.Drawing.Common.dll, but also has runtimes/{win,unix}/lib/netcoreapp2.0/System.Drawing.Common.dll
// In this case, the host will pick the rid-specific version
var path = TestResources.GetTestProjectAssembly("DrawingApp");
var loader = PluginLoader.CreateFromConfigFile(path);
var assembly = loader.LoadDefaultAssembly();
var type = assembly.GetType("Finder", throwOnError: true);
var method = type.GetMethod("FindDrawingAssembly", BindingFlags.Static | BindingFlags.Public);
Assert.NotNull(method);
Assert.Contains("runtimes", (string)method.Invoke(null, Array.Empty<object>()));
}
[Fact]
[UseCulture("es")]
public void ItLoadsSatelliteAssemblies()
@ -71,7 +88,7 @@ namespace McMaster.NETCore.Plugins.Tests
var loader = PluginLoader.CreateFromConfigFile(path, sharedTypes: new[] { typeof(IFruit) });
var assembly = loader.LoadDefaultAssembly();
var type = Assert.Single(assembly.GetTypes(), t => typeof(IFruit).IsAssignableFrom(t));
return (IFruit) Activator.CreateInstance(type);
return (IFruit)Activator.CreateInstance(type);
}
}
}

View File

@ -15,6 +15,7 @@
<ProjectReference Include="..\..\src\Plugins\McMaster.NETCore.Plugins.csproj" />
<ProjectReference Include="..\TestProjects\ReferencedLibv1\ReferencedLibv1.csproj" />
<TestProject Include="..\TestProjects\ReferencedLibv2\ReferencedLibv2.csproj" />
<TestProject Include="..\TestProjects\DrawingApp\DrawingApp.csproj" />
<TestProject Include="..\TestProjects\NetCoreApp20App\NetCoreApp20App.csproj" />
<TestProject Include="..\TestProjects\NetStandardClassLib\NetStandardClassLib.csproj" />
<TestProject Include="..\TestProjects\JsonNet9\JsonNet9.csproj" />

View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="4.5.1" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,11 @@
using System.Drawing.Printing;
public class Finder
{
public static string FindDrawingAssembly()
{
var pd = new PrintDocument();
return typeof(PrintDocument).Assembly.CodeBase;
}
}