Skip to content

Commit

Permalink
Fix #25 - fix loading in MVC sample and add fallback to loading assem…
Browse files Browse the repository at this point in the history
…blies from the plugin base directory
  • Loading branch information
natemcmaster committed Jan 15, 2019
1 parent 56f4692 commit f1d4566
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 42 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ obj/
.vs/
artifacts/
.idea/
*.user
launchSettings.json
41 changes: 38 additions & 3 deletions DotNetCorePlugins.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28407.52
# Visual Studio 15
VisualStudioVersion = 15.0.28307.271
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{471CA3C0-0BC9-4C0C-A013-D9356DBD0F38}"
EndProject
Expand Down Expand Up @@ -62,7 +62,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plátano", "test\TestProjec
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DrawingApp", "test\TestProjects\DrawingApp\DrawingApp.csproj", "{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqlClientApp", "test\TestProjects\SqlClientApp\SqlClientApp.csproj", "{0CDA2765-C9DF-45EE-A099-0E2D4A980E59}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SqlClientApp", "test\TestProjects\SqlClientApp\SqlClientApp.csproj", "{0CDA2765-C9DF-45EE-A099-0E2D4A980E59}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MvcApp", "samples\aspnetcore-mvc\MvcApp\MvcApp.csproj", "{F934B760-4847-4BA8-9F6A-7F750ECF2328}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MvcAppPlugin1", "samples\aspnetcore-mvc\MvcAppPlugin1\MvcAppPlugin1.csproj", "{2DC38785-B7B6-49E9-84D4-103A56D3604A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{F49FFE3B-E1AE-483E-951F-D498F6ABA08E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "aspnetcoremvc", "aspnetcoremvc", "{610E8065-1F29-41E8-A3FC-07ABDF16C8BB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -278,6 +286,30 @@ Global
{0CDA2765-C9DF-45EE-A099-0E2D4A980E59}.Release|x64.Build.0 = Release|Any CPU
{0CDA2765-C9DF-45EE-A099-0E2D4A980E59}.Release|x86.ActiveCfg = Release|Any CPU
{0CDA2765-C9DF-45EE-A099-0E2D4A980E59}.Release|x86.Build.0 = Release|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Debug|x64.ActiveCfg = Debug|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Debug|x64.Build.0 = Debug|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Debug|x86.ActiveCfg = Debug|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Debug|x86.Build.0 = Debug|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Release|Any CPU.Build.0 = Release|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Release|x64.ActiveCfg = Release|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Release|x64.Build.0 = Release|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Release|x86.ActiveCfg = Release|Any CPU
{F934B760-4847-4BA8-9F6A-7F750ECF2328}.Release|x86.Build.0 = Release|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Debug|x64.ActiveCfg = Debug|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Debug|x64.Build.0 = Debug|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Debug|x86.ActiveCfg = Debug|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Debug|x86.Build.0 = Debug|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Release|Any CPU.Build.0 = Release|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Release|x64.ActiveCfg = Release|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Release|x64.Build.0 = Release|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Release|x86.ActiveCfg = Release|Any CPU
{2DC38785-B7B6-49E9-84D4-103A56D3604A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -301,6 +333,9 @@ Global
{5889B0C9-50E5-4FDC-933B-8684B9FAB8E4} = {98E964A2-55DA-4740-9F2E-B64FDF6715DB}
{8BE0F92F-F353-4D63-9C6F-50D4A0BB7FAB} = {98E964A2-55DA-4740-9F2E-B64FDF6715DB}
{0CDA2765-C9DF-45EE-A099-0E2D4A980E59} = {98E964A2-55DA-4740-9F2E-B64FDF6715DB}
{F934B760-4847-4BA8-9F6A-7F750ECF2328} = {610E8065-1F29-41E8-A3FC-07ABDF16C8BB}
{2DC38785-B7B6-49E9-84D4-103A56D3604A} = {610E8065-1F29-41E8-A3FC-07ABDF16C8BB}
{610E8065-1F29-41E8-A3FC-07ABDF16C8BB} = {F49FFE3B-E1AE-483E-951F-D498F6ABA08E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B1AF41DC-A03E-47B1-BBDB-3DC27ABD9F74}
Expand Down
1 change: 1 addition & 0 deletions releasenotes.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<![CDATA[
Bug fix:
* Fix loading plugins which use SqlClient on Windows.
* Fallback to loading assemblies from the plugin base directory when all else fails.
]]>
</PackageReleaseNotes>
<PackageReleaseNotes Condition="'$(VersionPrefix)' == '0.2.1'">
Expand Down
4 changes: 2 additions & 2 deletions samples/aspnetcore-mvc/MvcApp/MvcApp.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
Expand All @@ -15,7 +15,7 @@
<ProjectReference Include="$(RepoRoot)src\Plugins\McMaster.NETCore.Plugins.csproj" />
</ItemGroup>

<Target Name="BuildPlugin" AfterTargets="Build">
<Target Name="BuildPlugin" BeforeTargets="Build">
<MSBuild Projects="..\MvcAppPlugin1\MvcAppPlugin1.csproj"
Targets="Publish"
Properties="Configuration=$(Configuration);PublishDir=$(OutputPath)/plugins/MvcAppPlugin1/" />
Expand Down
9 changes: 1 addition & 8 deletions samples/aspnetcore-mvc/MvcApp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace MvcWebApp
{
Expand Down
14 changes: 5 additions & 9 deletions samples/aspnetcore-mvc/MvcApp/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Reflection;
using McMaster.NETCore.Plugins;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace MvcWebApp
Expand Down Expand Up @@ -39,9 +33,10 @@ public void ConfigureServices(IServiceCollection services)
}

// This piece finds and loads related parts, such as MvcAppPlugin1.Views.dll.
var relatedAssemblies = RelatedAssemblyAttribute.GetRelatedAssemblies(pluginAssembly, throwOnError: true);
foreach (var assembly in relatedAssemblies)
var relatedAssembliesAttrs = pluginAssembly.GetCustomAttributes<RelatedAssemblyAttribute>();
foreach (var attr in relatedAssembliesAttrs)
{
var assembly = plugin.LoadAssembly(attr.AssemblyFileName);
partFactory = ApplicationPartFactory.GetApplicationPartFactory(assembly);
foreach (var part in partFactory.GetApplicationParts(assembly))
{
Expand All @@ -54,6 +49,7 @@ public void ConfigureServices(IServiceCollection services)

public void Configure(IApplicationBuilder app)
{
app.UseDeveloperExceptionPage();
app.UseMvcWithDefaultRoute();
}
}
Expand Down
76 changes: 56 additions & 20 deletions src/Plugins/Loader/ManagedLoadContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,22 @@ protected override Assembly Load(AssemblyName assemblyName)
return null;
}

if (_managedAssemblies.TryGetValue(assemblyName.Name, out var library)
&& SearchForLibrary(library, out var path))
if (_managedAssemblies.TryGetValue(assemblyName.Name, out var library))
{
return LoadFromAssemblyPath(path);
if (SearchForLibrary(library, out var path))
{
return LoadFromAssemblyPath(path);
}
}
else
{
// if an assembly was not listed in the list of known assemblies,
// fallback to the load context base directory
var localFile = Path.Combine(_basePath, assemblyName.Name + ".dll");
if (File.Exists(localFile))
{
return LoadFromAssemblyPath(localFile);
}
}

return null;
Expand All @@ -114,29 +126,53 @@ protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
{
foreach (var prefix in PlatformInformation.NativeLibraryPrefixes)
{
if (_nativeLibraries.TryGetValue(prefix + unmanagedDllName, out var library)
&& SearchForLibrary(library, prefix, out var path))
if (_nativeLibraries.TryGetValue(prefix + unmanagedDllName, out var library))
{
return LoadUnmanagedDllFromPath(path);
if (SearchForLibrary(library, prefix, out var path))
{
return LoadUnmanagedDllFromPath(path);
}
}

// coreclr allows code to use [DllImport("sni")] or [DllImport("sni.dll")]
// This library treats the file name without the extension as the lookup name,
// so this loop is necessary to check if the unmanaged name matches a library
// when the file extension has been trimmed.
foreach (var suffix in PlatformInformation.NativeLibraryExtensions)
else
{
if (!unmanagedDllName.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
// coreclr allows code to use [DllImport("sni")] or [DllImport("sni.dll")]
// This library treats the file name without the extension as the lookup name,
// so this loop is necessary to check if the unmanaged name matches a library
// when the file extension has been trimmed.
foreach (var suffix in PlatformInformation.NativeLibraryExtensions)
{
continue;
if (!unmanagedDllName.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
{
continue;
}

// check to see if there is a library entry for the library without the file extension
var trimmedName = unmanagedDllName.Substring(0, unmanagedDllName.Length - suffix.Length);

if (_nativeLibraries.TryGetValue(prefix + trimmedName, out library))
{
if (SearchForLibrary(library, prefix, out var path))
{
return LoadUnmanagedDllFromPath(path);
}
}
else
{
// fallback to native assets which match the file name in the plugin base directory
var localFile = Path.Combine(_basePath, prefix + unmanagedDllName + suffix);
if (File.Exists(localFile))
{
return LoadUnmanagedDllFromPath(localFile);
}

var localFileWithoutSuffix = Path.Combine(_basePath, prefix + unmanagedDllName);
if (File.Exists(localFileWithoutSuffix))
{
return LoadUnmanagedDllFromPath(localFileWithoutSuffix);
}
}
}
var trimmedName = unmanagedDllName.Substring(0, unmanagedDllName.Length - suffix.Length);

if (_nativeLibraries.TryGetValue(prefix + trimmedName, out library)
&& SearchForLibrary(library, prefix, out path))
{
return LoadUnmanagedDllFromPath(path);
}
}
}

Expand Down

0 comments on commit f1d4566

Please sign in to comment.