Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AssemblyResolve handler for in-memory assemblies in CodeTaskFactory #1486

Merged
merged 2 commits into from
Dec 18, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/XMakeTasks/CodeTaskFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,37 @@ namespace Microsoft.Build.Tasks
/// </summary>
public class CodeTaskFactory : ITaskFactory
{
/// <summary>
/// This dictionary keeps track of custom references to compiled assemblies. The in-memory assembly is loaded from a byte
/// stream and as such its dependencies cannot be found unless they are in the MSBuild.exe directory or the GAC. They
/// cannot be found even if they are already loaded in the AppDomain. This dictionary knows the FullName of the assembly
/// and a reference to the assembly itself. In the <see cref="CurrentDomainOnAssemblyResolve"/> handler, the dictionary
/// is used to return the loaded assemblies as a way to allow custom references that are not in the normal assembly Load
/// context.
/// </summary>
private static readonly IDictionary<string, Assembly> s_knownReferenceAssemblies = new ConcurrentDictionary<string, Assembly>(StringComparer.OrdinalIgnoreCase);

static CodeTaskFactory()
{
// The handler is not detached because it only returns assemblies for custom references that cannot be found in the normal Load context
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve;
}

/// <summary>
/// Handles the <see cref="AppDomain.AssemblyResolve"/> event to return assemblies loaded from custom references.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <returns></returns>
private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
{
Assembly assembly = null;
// Return the assembly loaded from the custom reference if the FullName matches what is being looked for
s_knownReferenceAssemblies.TryGetValue(args.Name, out assembly);

return assembly;
}

/// <summary>
/// Default assemblies names to reference during inline code compilation - from the .NET Framework
/// </summary>
Expand Down Expand Up @@ -657,6 +688,7 @@ private void AddReferenceAssemblyToReferenceList(List<string> referenceAssemblyL
if (candidateAssembly != null)
{
candidateAssemblyLocation = candidateAssembly.Location;
s_knownReferenceAssemblies[candidateAssembly.FullName] = candidateAssembly;
}
}
catch (BadImageFormatException e)
Expand Down