Skip to content
This repository has been archived by the owner on Dec 18, 2017. It is now read-only.

Commit

Permalink
Plumb assembly name throughout the loaders
Browse files Browse the repository at this point in the history
- Changed Load(string) to Load(AssemblyName)
- Kept Load(string) via an extension method
  • Loading branch information
davidfowl committed May 21, 2015
1 parent 6722e1f commit e9b8144
Show file tree
Hide file tree
Showing 23 changed files with 132 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Versioning;
using System.Threading;
using Microsoft.Framework.DesignTimeHost.Models;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public Assembly LoadStream(Stream assemblyStream, Stream pdbStream)
return null;
}

public Assembly Load(string name)
public Assembly Load(AssemblyName assemblyName)
{
throw new NotSupportedException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Versioning;
using Microsoft.Framework.PackageManager.Algorithms;
using Microsoft.Framework.Runtime;
Expand Down Expand Up @@ -152,7 +153,7 @@ private string ResolveAssemblyFilePath(string assemblyName)

// Look into the NuGets then.
PackageAssembly assembly;
if (_hostContext.NuGetDependencyProvider.PackageAssemblyLookup.TryGetValue(assemblyName, out assembly))
if (_hostContext.NuGetDependencyProvider.PackageAssemblyLookup.TryGetValue(new AssemblyName(assemblyName), out assembly))
{
return assembly.Path;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Reflection;

namespace Microsoft.Framework.Runtime
{
public static class AssemblyLoadContextExtensions
{
public static Assembly Load(this IAssemblyLoadContext loadContext, string name)
{
return loadContext.Load(new AssemblyName(name));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ public interface IAssemblyLoadContext : IDisposable
/// <summary>
/// Load an assembly by name.
/// </summary>
/// <param name="name">The name of the assembly.</param>
/// <param name="assemblyName">The name of the assembly.</param>
/// <returns>The loaded assembly.</returns>
Assembly Load(string name);
Assembly Load(AssemblyName assemblyName);

/// <summary>
/// Loads the assembly located at the provided file system path.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public interface IAssemblyLoader
/// <summary>
/// Load an assembly by name.
/// </summary>
/// <param name="name">The name of the assembly.</param>
/// <param name="assemblyName">The name of the assembly.</param>
/// <returns>The loaded assembly.</returns>
Assembly Load(string name);
Assembly Load(AssemblyName assemblyName);
}
}
27 changes: 24 additions & 3 deletions src/Microsoft.Framework.Runtime.Loader/AssemblyLoaderCache.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;

namespace Microsoft.Framework.Runtime.Loader
{
internal class AssemblyLoaderCache
{
private readonly ConcurrentDictionary<string, object> _assemblyLoadLocks = new ConcurrentDictionary<string, object>(StringComparer.Ordinal);
private readonly ConcurrentDictionary<string, Assembly> _assemblyCache = new ConcurrentDictionary<string, Assembly>(StringComparer.Ordinal);
private readonly ConcurrentDictionary<AssemblyName, object> _assemblyLoadLocks = new ConcurrentDictionary<AssemblyName, object>(AssemblyNameComparer.Ordinal);
private readonly ConcurrentDictionary<AssemblyName, Assembly> _assemblyCache = new ConcurrentDictionary<AssemblyName, Assembly>(AssemblyNameComparer.Ordinal);

public Assembly GetOrAdd(string name, Func<string, Assembly> factory)
public Assembly GetOrAdd(AssemblyName name, Func<AssemblyName, Assembly> factory)
{
// If the assembly was already loaded use it
Assembly assembly;
Expand Down Expand Up @@ -48,5 +49,25 @@ public Assembly GetOrAdd(string name, Func<string, Assembly> factory)

return assembly;
}

private class AssemblyNameComparer : IEqualityComparer<AssemblyName>
{
public static IEqualityComparer<AssemblyName> Ordinal = new AssemblyNameComparer();

public bool Equals(AssemblyName x, AssemblyName y)
{
return
string.Equals(x.Name, y.Name, StringComparison.Ordinal) &&
string.Equals(x.CultureName, y.CultureName, StringComparison.Ordinal);
}

public int GetHashCode(AssemblyName obj)
{
var hashCode = 0;
if (obj.Name != null) hashCode ^= obj.Name.GetHashCode();
if (obj.CultureName != null) hashCode ^= obj.CultureName.GetHashCode();
return hashCode;
}
}
}
}
33 changes: 18 additions & 15 deletions src/Microsoft.Framework.Runtime.Loader/LoadContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,15 @@ public abstract class LoadContext : AssemblyLoadContext, IAssemblyLoadContext

protected override Assembly Load(AssemblyName assemblyName)
{
var name = assemblyName.Name;

return _cache.GetOrAdd(name, LoadAssembly);
return _cache.GetOrAdd(assemblyName, LoadAssembly);
}

public Assembly Load(string name)
Assembly IAssemblyLoadContext.Load(AssemblyName assemblyName)
{
return LoadFromAssemblyName(new AssemblyName(name));
return LoadFromAssemblyName(assemblyName);
}

public abstract Assembly LoadAssembly(string name);
public abstract Assembly LoadAssembly(AssemblyName assemblyName);

public Assembly LoadFile(string path)
{
Expand Down Expand Up @@ -128,22 +126,25 @@ public void Dispose()
_contextId = null;
}

public Assembly Load(string name)
public Assembly Load(AssemblyName assemblyName)
{
if (string.IsNullOrEmpty(_contextId))
{
return Assembly.Load(name);
return Assembly.Load(assemblyName);
}

return Assembly.Load(_contextId + "$" + name);
var contextIdAssemblyName = (AssemblyName)assemblyName.Clone();
contextIdAssemblyName.Name = _contextId + "$" + assemblyName.Name;

return Assembly.Load(contextIdAssemblyName);
}

private Assembly LoadAssemblyImpl(string name)
private Assembly LoadAssemblyImpl(AssemblyName assemblyName)
{
return _cache.GetOrAdd(name, LoadAssembly);
return _cache.GetOrAdd(assemblyName, LoadAssembly);
}

public abstract Assembly LoadAssembly(string name);
public abstract Assembly LoadAssembly(AssemblyName assemblyName);

public Assembly LoadFile(string assemblyPath)
{
Expand Down Expand Up @@ -204,7 +205,9 @@ private static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
LoadContext context;
if (_contexts.TryGetValue(contextId, out context))
{
var assembly = context.LoadAssemblyImpl(shortName);
var shortAssemblyName = (AssemblyName)assemblyName.Clone();
shortAssemblyName.Name = shortName;
var assembly = context.LoadAssemblyImpl(shortAssemblyName);

if (assembly != null)
{
Expand All @@ -230,13 +233,13 @@ private static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
var loadContext = LoadContextAccessor.Instance.GetLoadContext(args.RequestingAssembly);
if (loadContext != null)
{
return loadContext.Load(assemblyName.Name);
return loadContext.Load(assemblyName);
}
}
else
{
// Nothing worked, use the default load context
return Default.LoadAssemblyImpl(assemblyName.Name);
return Default.LoadAssemblyImpl(assemblyName);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Versioning;
using Microsoft.Framework.Runtime.Compilation;
using Microsoft.Framework.Runtime.DependencyManagement;
Expand All @@ -18,7 +19,7 @@ public class NuGetDependencyResolver : IDependencyProvider, ILibraryExportProvid
private readonly PackageRepository _repository;

// Assembly name and path lifted from the appropriate lib folder
private readonly Dictionary<string, PackageAssembly> _packageAssemblyLookup = new Dictionary<string, PackageAssembly>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<AssemblyName, PackageAssembly> _packageAssemblyLookup = new Dictionary<AssemblyName, PackageAssembly>(AssemblyNameComparer.OrdinalIgnoreCase);

// All the information required by this package
private readonly Dictionary<string, PackageDescription> _packageDescriptions = new Dictionary<string, PackageDescription>(StringComparer.OrdinalIgnoreCase);
Expand All @@ -29,7 +30,7 @@ public NuGetDependencyResolver(PackageRepository repository)
Dependencies = Enumerable.Empty<LibraryDescription>();
}

public IDictionary<string, PackageAssembly> PackageAssemblyLookup
public IDictionary<AssemblyName, PackageAssembly> PackageAssemblyLookup
{
get
{
Expand Down Expand Up @@ -280,6 +281,7 @@ public void Initialize(IEnumerable<LibraryDescription> packages, FrameworkName t
{
var name = Path.GetFileNameWithoutExtension(assemblyPath);
var path = Path.Combine(dependency.Path, assemblyPath);
var assemblyName = new AssemblyName(name);

string replacementPath;
if (Servicing.ServicingTable.TryGetReplacement(
Expand All @@ -288,7 +290,7 @@ public void Initialize(IEnumerable<LibraryDescription> packages, FrameworkName t
assemblyPath,
out replacementPath))
{
_packageAssemblyLookup[name] = new PackageAssembly()
_packageAssemblyLookup[assemblyName] = new PackageAssembly()
{
Path = replacementPath,
RelativePath = assemblyPath,
Expand All @@ -297,7 +299,7 @@ public void Initialize(IEnumerable<LibraryDescription> packages, FrameworkName t
}
else
{
_packageAssemblyLookup[name] = new PackageAssembly()
_packageAssemblyLookup[assemblyName] = new PackageAssembly()
{
Path = path,
RelativePath = assemblyPath,
Expand Down Expand Up @@ -457,7 +459,7 @@ public static string ResolveRepositoryPath(string rootDirectory)

var runtimePackages = Environment.GetEnvironmentVariable(EnvironmentNames.Packages);

if(string.IsNullOrEmpty(runtimePackages))
if (string.IsNullOrEmpty(runtimePackages))
{
runtimePackages = Environment.GetEnvironmentVariable(EnvironmentNames.DnxPackages);
}
Expand Down Expand Up @@ -501,5 +503,25 @@ private class AssemblyDescription

public string RelativePath { get; set; }
}

private class AssemblyNameComparer : IEqualityComparer<AssemblyName>
{
public static IEqualityComparer<AssemblyName> OrdinalIgnoreCase = new AssemblyNameComparer();

public bool Equals(AssemblyName x, AssemblyName y)
{
return
string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase) &&
string.Equals(x.CultureName, y.CultureName, StringComparison.OrdinalIgnoreCase);
}

public int GetHashCode(AssemblyName obj)
{
var hashCode = 0;
if (obj.Name != null) hashCode ^= obj.Name.ToUpperInvariant().GetHashCode();
if (obj.CultureName != null) hashCode ^= obj.CultureName.ToUpperInvariant().GetHashCode();
return hashCode;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ private class LibraryAssemblyLoadContext : LoadContext
_defaultContext = defaultContext;
}

public override Assembly LoadAssembly(string name)
public override Assembly LoadAssembly(AssemblyName assemblyName)
{
try
{
return _defaultContext.Load(name);
return _defaultContext.Load(assemblyName);
}
catch (FileNotFoundException)
{
return _projectAssemblyLoader.Load(name, this) ??
_nugetAssemblyLoader.Load(name, this);
return _projectAssemblyLoader.Load(assemblyName, this) ??
_nugetAssemblyLoader.Load(assemblyName, this);
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/Microsoft.Framework.Runtime/Loader/NuGetAssemblyLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ public class NuGetAssemblyLoader : IAssemblyLoader
_loadContextAccessor = loadContextAccessor;
}

public Assembly Load(string name)
public Assembly Load(AssemblyName assemblyName)
{
return Load(name, _loadContextAccessor.Default);
return Load(assemblyName, _loadContextAccessor.Default);
}

public Assembly Load(string name, IAssemblyLoadContext loadContext)
public Assembly Load(AssemblyName assemblyName, IAssemblyLoadContext loadContext)
{
PackageAssembly assemblyInfo;
if (_dependencyResolver.PackageAssemblyLookup.TryGetValue(name, out assemblyInfo))
if (_dependencyResolver.PackageAssemblyLookup.TryGetValue(assemblyName, out assemblyInfo))
{
return loadContext.LoadFile(assemblyInfo.Path);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ internal class ProjectAssemblyLoader : IAssemblyLoader
_libraryManager = libraryManager;
}

public Assembly Load(string name)
public Assembly Load(AssemblyName assemblyName)
{
return Load(name, _loadContextAccessor.Default);
return Load(assemblyName, _loadContextAccessor.Default);
}

public Assembly Load(string name, IAssemblyLoadContext loadContext)
public Assembly Load(AssemblyName assemblyName, IAssemblyLoadContext loadContext)
{
// An assembly name like "MyLibrary!alternate!more-text"
// is parsed into:
Expand All @@ -37,6 +37,7 @@ public Assembly Load(string name, IAssemblyLoadContext loadContext)
// and the more-text may be used to force a recompilation of an aspect that would
// otherwise have been cached by some layer within Assembly.Load

var name = assemblyName.Name;
string aspect = null;
var parts = name.Split(new[] { '!' }, 3);
if (parts.Length != 1)
Expand Down
4 changes: 2 additions & 2 deletions src/dnx.host/DefaultLoadContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ public DefaultLoadContext(LoaderContainer loaderContainer)
_loaderContainer = loaderContainer;
}

public override Assembly LoadAssembly(string name)
public override Assembly LoadAssembly(AssemblyName assemblyName)
{
return _loaderContainer.Load(name);
return _loaderContainer.Load(assemblyName);
}
}
}
8 changes: 4 additions & 4 deletions src/dnx.host/LoaderContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ public IDisposable AddLoader(IAssemblyLoader loader)
});
}

public Assembly Load(string name)
public Assembly Load(AssemblyName assemblyName)
{
Logger.TraceInformation("[{0}]: Load name={1}", GetType().Name, name);
Logger.TraceInformation("[{0}]: Load name={1}", GetType().Name, assemblyName);
var sw = Stopwatch.StartNew();

foreach (var loader in _loaders.Reverse())
{
var assembly = loader.Load(name);
var assembly = loader.Load(assemblyName);
if (assembly != null)
{
Logger.TraceInformation("[{0}]: Loaded name={1} in {2}ms", loader.GetType().Name, name, sw.ElapsedMilliseconds);
Logger.TraceInformation("[{0}]: Loaded name={1} in {2}ms", loader.GetType().Name, assemblyName, sw.ElapsedMilliseconds);
return assembly;
}
}
Expand Down

0 comments on commit e9b8144

Please sign in to comment.