-
Notifications
You must be signed in to change notification settings - Fork 32
#123 Support module nested references loading in Platform modular system. #124
Conversation
// Explicit loading of "ICSharpCode.SharpZipLib.dll" (dependency of referenced assembly Module1.Data) to default ALC would make test passing even without proper dependency loading: | ||
// System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromAssemblyPath(Environment.ExpandEnvironmentVariables(@"%userprofile%\.nuget\packages\sharpziplib\1.1.0\lib\netstandard2.0\ICSharpCode.SharpZipLib.dll")); | ||
var controllerType = webRuntimeAssembly.GetType("Module1.Web.Controllers.ThirdPartyController"); | ||
Assert.NotNull(controllerType); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public class AssemblyLoadTest | ||
{ | ||
[Fact] | ||
public void TestAssemblyLoadThroughReflection() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
<ItemGroup> | ||
<Reference Include="Microsoft.Extensions.Logging.Abstractions"> | ||
<HintPath>..\..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.logging.abstractions\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove
<!--<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>--> | ||
<!--This line is necessary to copy all dependencies in the bin folder--> | ||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> | ||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe it is redundant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In implented dependency load system with copying all dependencies to output it is required. Will try to avoid dependency assembly copying by including NuGet and .NET caches to additional probing paths.
Explanation:
Set win10-x64 option to VirtoCommerce.ImageToolsModule.Web project to address problem with NuGet package Microsoft.Windows.Compatibility, which do not copy its dependency "System.Private.ServiceModel.dll" on publishing. Explicit reference to System.ServiceModel.Http 4.5.3 package did not help, setting RID helped, though it makes module platform dependent. Info:
dotnet/wcf#2349, https://stackoverflow.com/questions/50746592/system-private-servicemodel-missing-in-azure-app-service-at-runtime;
var bytes = Encoding.UTF8.GetBytes(message); | ||
using (var inStream = new MemoryStream(bytes)) | ||
{ | ||
var outStream = CreateToMemoryStream(inStream, "TestZipEntry"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using or close
namespace VirtoCommerce.Platform.Modules.AssemblyLoading | ||
{ | ||
// Based on https://github.com/natemcmaster/DotNetCorePlugins/blob/ce1b5cc94e8e9ce018f9304368cc69897cc70cca/src/Plugins/Loader/DependencyContextExtensions.cs | ||
public static class DependencyReader |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not extension. bad idea use static, better to use with DI, read https://stackoverflow.com/questions/241339/when-to-use-static-classes-in-c-sharp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think is ok, just need to change methods signatures to be more like to extensions class semantic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Read the SO post and think that it is still a suitable choice as it is true utility class with strictly defined function.
Could change it back to an extension.
// Fill _basePath and _additionalProbingPaths based on assemblyPath | ||
// In fact we could add some _additionalProbingPaths to support assembly storages like NuGet package cache (), if we would need | ||
var assemblyDirectory = Path.GetDirectoryName(assemblyUri.LocalPath); | ||
_basePath = assemblyDirectory; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not really good to change object field inside read only functions, could we avoid this?
private bool SearchForLibrary(ManagedLibrary library, out string path) | ||
{ | ||
// 1. Check for in _basePath + app local path | ||
var localFile = Path.Combine(_basePath, library.AppLocalPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this code cognitive complexity can be simplified by generation array of search paths and do single linq call FirstOrDefault
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Candidates pregeneration will add significant overhead. The common scenario would be just finding dependency inside _basePath, which generally speaking means one string creation, comparison and return. Sometimes dependency could be found inside _additionalProbingPaths, it could add couple of string creations. If we will pregenerate all the strings, method would become about 5 times slower.
And i think algorithm is readable and self-described, probably algorithm readability would not change much if we switch to pregeneration array.
Is generalization here costs 5-times performance loss?
private static IEnumerable<ManagedLibrary> ResolveRuntimeAssemblies(DependencyContext depContext, RuntimeFallbacks runtimeGraph) | ||
{ | ||
var rids = GetRids(runtimeGraph); | ||
return from library in depContext.RuntimeLibraries |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you replace this linq expression to extensions method syntax?
{ | ||
bool assemblyPredicate(RuntimeLibrary runtime) | ||
var loadedAssembly = LoadAssemblyCached(dependency) ?? throw GenerateAssemblyLoadException(dependency.Name.Name, assemblyPath); | ||
if (mainAssemblyName.Equals(loadedAssembly.GetName().Name, StringComparison.OrdinalIgnoreCase)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be replaced with .EqualsInvariant
- Used PluginLoader for this;
…tem: - Reworked LoadContextAssemblyResolver assembly loading: every module assembly with all level dependencies is loaded into AssemblyLoadContext.Default to allow shared types to be used; - Set all module Web projects <CopyLocalLockFileAssemblies> option to true to have the possibility to copy all dependencies from its bin folder (using this approach it should work on prod env where we cannot just restore packages). Futher investigation and revision could be done based on: https://github.com/dotnet/cli/issues/10502; - Set <RuntimeIdentifier>win10-x64</RuntimeIdentifier> option to VirtoCommerce.ImageToolsModule.Web project to address problem with NuGet package Microsoft.Windows.Compatibility, which do not copy its dependency "System.Private.ServiceModel.dll" on publishing. Explicit reference to System.ServiceModel.Http 4.5.3 package did not help, setting RID helped, though it makes module platform dependent. Info: dotnet/wcf#2349, https://stackoverflow.com/questions/50746592/system-private-servicemodel-missing-in-azure-app-service-at-runtime; - Removed redundant LoadContextAssemblyResolver singleton registration; - Changed Windows specific "\" path separator to platform independent Path.DirectorySeparatorChar in LocalStorageModuleCatalog probing folder; - Fixed Sonar warning in ModuleInitializer.
…tem: - Excluded copying assembly related dlls that are in TPA; - Splitted assembly file extensions (dll, exe) and assembly service file extensions (pdb, xml, .deps.json) for using in filtering; - Removed unused McMaster.NETCore.Plugins package reference from VirtoCommerce.Platform.Modules.csproj; - Fixed couple of Sonar warnings;
…tem: - Implemented "api/platform/modules/restart" action using IApplicationLifetime.StopApplication();
…tem: - Added AdditionalProbingPath filling based on runtimeconfig.json and runtimeconfig.dev.json for Development env + NuGet and DotNet package caches for Production env; - Removed all NuGet assembly copying to Modules probing folder. So it works on DEV env, for PROD we will need to prepare packages with required dependencies; - Rebased on the latest master; Review: - Reworked test according to https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-best-practices; - Arranged DependencyReader as an extension; - Other fixes;
44a179c
to
3007f80
Compare
…tem: - Removed copying NuGet assemblies to output in Module1;
dotnet/cli#10502;
.NET Core 2.0 self-contained app: Could not load file or assembly 'System.Private.ServiceModel, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' dotnet/wcf#2349, https://stackoverflow.com/questions/50746592/system-private-servicemodel-missing-in-azure-app-service-at-runtime;