natemcmaster / DotNetCorePlugins

.NET Core library for dynamically loading code

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Is it safe to use all the time config.PreferSharedTypes to true in using pluginloader?

kgorro opened this issue · comments

A dotnet profiler is dynamically loading an assembly which uses types that reference might causes system.io.fileload exception.
Is it recommended to use config.PreferSharedTypes = true ? Or Is it possible to have a feature which you can specify a config to exclude an assembly to be loaded in default load context?

"safe" is an ambiguous term here, so not sure how to answer. That said, take a look at what PluginLoader is doing under the hood. I chose two sets of behaviors that I thought were sensible defaults. I also provided a lower-level API called AssemblyLoadContextBuilder which allows you finer grained control to define your own loading behaviors. For example, checkout

/// <summary>
/// Instructs the load context to prefer a private version of this assembly, even if that version is
/// different from the version used by the host application.
/// Use this when you do not need to exchange types created from within the load context with other contexts
/// or the default app context.
/// <para>
/// This may mean the types loaded from
/// this assembly will not match the types from an assembly with the same name, but different version,
/// in the host application.
/// </para>
/// <para>
/// For example, if the host application has a type named <c>Foo</c> from assembly <c>Banana, Version=1.0.0.0</c>
/// and the load context prefers a private version of <c>Banan, Version=2.0.0.0</c>, when comparing two objects,
/// one created by the host (Foo1) and one created from within the load context (Foo2), they will not have the same
/// type. <c>Foo1.GetType() != Foo2.GetType()</c>
/// </para>
/// </summary>
/// <param name="assemblyName">The name of the assembly.</param>
/// <returns>The builder.</returns>
public AssemblyLoadContextBuilder PreferLoadContextAssembly(AssemblyName assemblyName)
{
if (assemblyName.Name != null)
{
_privateAssemblies.Add(assemblyName.Name);
}
return this;
}
/// <summary>
/// Instructs the load context to first attempt to load assemblies by this name from the default app context, even
/// if other assemblies in this load context express a dependency on a higher or lower version.
/// Use this when you need to exchange types created from within the load context with other contexts
/// or the default app context.
/// </summary>
/// <param name="assemblyName">The name of the assembly.</param>
/// <returns>The builder.</returns>
public AssemblyLoadContextBuilder PreferDefaultLoadContextAssembly(AssemblyName assemblyName)
{
// Lazy loaded references have dependencies resolved as they are loaded inside the actual Load Context.
if (_lazyLoadReferences)
{
if (assemblyName.Name != null && !_defaultAssemblies.Contains(assemblyName.Name))
{
_defaultAssemblies.Add(assemblyName.Name);
var assembly = _defaultLoadContext.LoadFromAssemblyName(assemblyName);
foreach (var reference in assembly.GetReferencedAssemblies())
{
if (reference.Name != null)
{
_defaultAssemblies.Add(reference.Name);
}
}
}
return this;
}
var names = new Queue<AssemblyName>();
names.Enqueue(assemblyName);
while (names.TryDequeue(out var name))
{
if (name.Name == null || _defaultAssemblies.Contains(name.Name))
{
// base cases
continue;
}
_defaultAssemblies.Add(name.Name);
// Load and find all dependencies of default assemblies.
// This sacrifices some performance for determinism in how transitive
// dependencies will be shared between host and plugin.
var assembly = _defaultLoadContext.LoadFromAssemblyName(name);
foreach (var reference in assembly.GetReferencedAssemblies())
{
names.Enqueue(reference);
}
}
return this;

The issue is when we tried to use the plugin loader with a dotnet profiler which loaded an assembly dynamically causes the application to crash. The main reason for this is that the assembly being loaded by the dotnet profiler is also being loaded by the plugin loader. To solve this we use config.PreferSharedTypes = true

This issue has been automatically marked as stale because it has no recent activity. It will be closed if no further activity occurs. Please comment if you believe this should remain open, otherwise it will be closed in 14 days. Thank you for your contributions to this project.

Closing due to inactivity.
If you are looking at this issue in the future and think it should be reopened, please make a commented here and mention natemcmaster so he sees the notification.