Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
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
118 changes: 5 additions & 113 deletions src/GitHub.VisualStudio/AssemblyResolverPackage.cs
Original file line number Diff line number Diff line change
@@ -1,124 +1,16 @@
using System;
using System.IO;
using System.Reflection;
using System.Globalization;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using NLog;

namespace GitHub.VisualStudio
{
// This fires before ShellInitialized and SolutionExists.
[ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string)]
// Allow assemblies in the extension directory to be resolved by their full or partial name.
// This is required for GitHub.VisualStudio.imagemanifest, XAML and when using unsigned assemblies.
// See: https://github.com/github/VisualStudio/pull/1236/
[ProvideBindingPath]

[Guid(Guids.guidAssemblyResolverPkgString)]
public class AssemblyResolverPackage : Package
{
// list of assemblies that should be considered when resolving
IEnumerable<ProvideDependentAssemblyAttribute> dependentAssemblies;
string packageFolder;

IDictionary<string, Assembly> resolvingAssemblies;
IDictionary<string, Exception> resolvingExceptions;

public AssemblyResolverPackage()
{
var asm = Assembly.GetExecutingAssembly();
packageFolder = Path.GetDirectoryName(asm.Location);
dependentAssemblies = asm.GetCustomAttributes<ProvideDependentAssemblyAttribute>();
resolvingAssemblies = new Dictionary<string, Assembly>();
resolvingExceptions = new Dictionary<string, Exception>();
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssemblyFromPackageFolder;
}

protected override void Dispose(bool disposing)
{
AppDomain.CurrentDomain.AssemblyResolve -= ResolveAssemblyFromPackageFolder;

if (resolvingAssemblies.Count > 0 || resolvingExceptions.Count > 0)
{
// Avoid executing any logging code unless there is something to log.
WriteToLog();
}

base.Dispose(disposing);
}

[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
public static Assembly ResolveDependentAssembly(
ProvideDependentAssemblyAttribute dependentAssembly, string packageFolder, AssemblyName resolveAssemblyName)
{
if (dependentAssembly.AssemblyName == resolveAssemblyName.Name)
{
var file = dependentAssembly.CodeBase.Replace("$PackageFolder$", packageFolder);
if (File.Exists(file))
{
var targetAssemblyName = AssemblyName.GetAssemblyName(file);

var codeBase = dependentAssembly as ProvideCodeBaseAttribute;
if (codeBase != null)
{
if (resolveAssemblyName.FullName == targetAssemblyName.FullName)
{
return Assembly.LoadFrom(file);
}
}

var bindingRedirection = dependentAssembly as ProvideBindingRedirectionAttribute;
if (bindingRedirection != null)
{
if (resolveAssemblyName.Version >= new Version(bindingRedirection.OldVersionLowerBound) &&
resolveAssemblyName.Version <= new Version(bindingRedirection.OldVersionUpperBound))
{
resolveAssemblyName.Version = targetAssemblyName.Version;
if (resolveAssemblyName.FullName == targetAssemblyName.FullName)
{
return Assembly.LoadFrom(file);
}
}
}
}
}

return null;
}

Assembly ResolveAssemblyFromPackageFolder(object sender, ResolveEventArgs e)
{
try
{
var resolveAssemblyName = new AssemblyName(e.Name);
foreach (var dependentAssembly in dependentAssemblies)
{
var resolvedAssembly = ResolveDependentAssembly(dependentAssembly, packageFolder, resolveAssemblyName);
if (resolvedAssembly != null)
{
return resolvingAssemblies[e.Name] = resolvedAssembly;
}
}
}
catch (Exception ex)
{
resolvingExceptions[e.Name] = ex;
}

return null;
}

void WriteToLog()
{
var log = LogManager.GetCurrentClassLogger();
foreach (var resolvedAssembly in resolvingAssemblies)
{
log.Info(CultureInfo.InvariantCulture, "Resolved '{0}' to '{1}'.", resolvedAssembly.Key, resolvedAssembly.Value.Location);
}

foreach (var resolvingException in resolvingExceptions)
{
log.Error(CultureInfo.InvariantCulture, "Error occurred loading '{0}' from '{1}'.\n{2}", resolvingException.Key, packageFolder, resolvingException.Value);
}
}
}
}
157 changes: 0 additions & 157 deletions src/UnitTests/GitHub.VisualStudio/AssemblyResolverPackageTests.cs

This file was deleted.

1 change: 0 additions & 1 deletion src/UnitTests/UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,6 @@
<Compile Include="GitHub.UI\Converters.cs" />
<Compile Include="GitHub.UI\TestAutomation\ResourceValueTests.cs" />
<Compile Include="GitHub.UI\TwoFactorInputTests.cs" />
<Compile Include="GitHub.VisualStudio\AssemblyResolverPackageTests.cs" />
<Compile Include="GitHub.VisualStudio\Services\JsonConnectionCacheTests.cs" />
<Compile Include="GitHub.VisualStudio\Services\ConnectionManagerTests.cs" />
<Compile Include="GitHub.VisualStudio\Services\RepositoryPublishServiceTests.cs" />
Expand Down