Browse Source

When loading referenced assemblies for code completion that have missing dependencies, try to find best available version.

For example, when using a library compiled against .NET 1.0; but only .NET 2.0 is installed, redirect the ReflectionOnlyAssemblyResolve event to load the .NET 2.0 version of System.dll instead.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@344 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
7d34f5b122
  1. 48
      src/Main/Base/Project/Src/Project/Items/ReferenceProjectItem.cs
  2. 2
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  3. 86
      src/Main/Base/Project/Src/Services/ParserService/ProjectContentRegistry.cs

48
src/Main/Base/Project/Src/Project/Items/ReferenceProjectItem.cs

@ -65,19 +65,22 @@ namespace ICSharpCode.SharpDevelop.Project @@ -65,19 +65,22 @@ namespace ICSharpCode.SharpDevelop.Project
try
{
string hintPath = HintPath;
if (hintPath != null && hintPath.Length > 0)
{
if (hintPath != null && hintPath.Length > 0) {
return Path.Combine(Project.Directory, hintPath);
}
string name = Path.Combine(Project.Directory, Include);
if (File.Exists(name))
{
if (File.Exists(name)) {
return name;
}
if (File.Exists(name + ".dll")) {
return name + ".dll";
}
if (File.Exists(name + ".exe")) {
return name + ".exe";
}
}
catch (Exception) { }
return GetPathToGACAssembly(Include);
return Include;
}
set {
// Set by file name is unsupported by references. (otherwise GAC references might have strange renaming effects ...)
@ -99,38 +102,5 @@ namespace ICSharpCode.SharpDevelop.Project @@ -99,38 +102,5 @@ namespace ICSharpCode.SharpDevelop.Project
Include,
Properties);
}
static string GetPathToGACAssembly(string referenceName)
{
string[] info = referenceName.Split(',');
if (info.Length < 4) {
try {
Assembly refAssembly = ProjectContentRegistry.LoadGACAssembly(referenceName, true);
// if it failed, then return just the short name
if (refAssembly == null) {
return info[0];
}
// split up the peices again to find the assembly file path
info = refAssembly.FullName.Split(',');
} catch (Exception) {
return referenceName;
}
}
string aName = info[0];
string aVersion = info[1].Substring(info[1].LastIndexOf('=') + 1);
string aPublicKey = info[3].Substring(info[3].LastIndexOf('=') + 1);
return FileUtility.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.System),
"..",
"assembly",
"GAC",
aName,
aVersion + "__" + aPublicKey,
aName + ".dll");
}
}
}

2
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -109,8 +109,10 @@ namespace ICSharpCode.Core @@ -109,8 +109,10 @@ namespace ICSharpCode.Core
{
try {
abortLoadSolutionProjectsThread = false;
LoggingService.Info("Start LoadSolutionProjects thread");
LoadSolutionProjectsInternal();
} finally {
LoggingService.Info("LoadSolutionProjects thread ended");
loadSolutionProjectsThread = null;
}
}

86
src/Main/Base/Project/Src/Services/ParserService/ProjectContentRegistry.cs

@ -19,6 +19,7 @@ using ICSharpCode.Core; @@ -19,6 +19,7 @@ using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Dom;
using MSjogren.GacTool.FusionNative;
namespace ICSharpCode.Core
{
@ -182,12 +183,9 @@ namespace ICSharpCode.Core @@ -182,12 +183,9 @@ namespace ICSharpCode.Core
static Assembly AssemblyResolve(object sender, ResolveEventArgs e)
{
string shortName = e.Name;
LoggingService.Debug("ProjectContentRegistry.AssemblyResolve" + e.Name);
int pos = shortName.IndexOf(',');
if (pos > 0)
shortName = shortName.Substring(0, pos);
string path = Path.Combine(lookupDirectory, shortName);
AssemblyName name = new AssemblyName(e.Name);
LoggingService.Debug("ProjectContentRegistry.AssemblyResolve " + e.Name);
string path = Path.Combine(lookupDirectory, name.Name);
if (File.Exists(path + ".dll")) {
LoggingService.Debug("AssemblyResolve ReflectionOnlyLoadFrom .dll file");
return Assembly.ReflectionOnlyLoadFrom(path + ".dll");
@ -203,10 +201,80 @@ namespace ICSharpCode.Core @@ -203,10 +201,80 @@ namespace ICSharpCode.Core
try {
LoggingService.Debug("AssemblyResolve trying ReflectionOnlyLoad");
return Assembly.ReflectionOnlyLoad(e.Name);
} catch (FileNotFoundException ex) {
LoggingService.Warn("AssemblyResolve failed: " + ex.Message);
return null;
} catch (FileNotFoundException) {
LoggingService.Warn("AssemblyResolve: ReflectionOnlyLoad failed for " + e.Name);
// We can't get the assembly we want.
// But propably we can get a similar version of it.
AssemblyName fixedName = FindBestMatchingAssemblyName(e.Name);
LoggingService.Info("AssemblyResolve: FixedName: " + fixedName);
return Assembly.ReflectionOnlyLoad(fixedName.FullName);
}
}
public static AssemblyName FindBestMatchingAssemblyName(string name)
{
string[] info = name.Split(',');
string version = (info.Length > 1) ? info[1].Substring(info[1].LastIndexOf('=') + 1) : null;
string publicKey = (info.Length > 3) ? info[3].Substring(info[3].LastIndexOf('=') + 1) : null;
IApplicationContext applicationContext = null;
IAssemblyEnum assemblyEnum = null;
IAssemblyName assemblyName;
Fusion.CreateAssemblyNameObject(out assemblyName, info[0], 0, 0);
Fusion.CreateAssemblyEnum(out assemblyEnum, null, assemblyName, 2, 0);
List<string> names = new List<string>();
while (assemblyEnum.GetNextAssembly(out applicationContext, out assemblyName, 0) == 0) {
uint nChars = 0;
assemblyName.GetDisplayName(null, ref nChars, 0);
StringBuilder sb = new StringBuilder((int)nChars);
assemblyName.GetDisplayName(sb, ref nChars, 0);
string fullName = sb.ToString();
if (publicKey != null) {
info = fullName.Split(',');
if (publicKey != info[3].Substring(info[3].LastIndexOf('=') + 1)) {
// Assembly has wrong public key
continue;
}
}
names.Add(fullName);
}
if (names.Count == 0)
return null;
string best = null;
Version bestVersion = null;
Version currentVersion;
if (version != null) {
// use assembly with lowest version higher or equal to required version
Version requiredVersion = new Version(version);
for (int i = 0; i < names.Count; i++) {
info = names[i].Split(',');
currentVersion = new Version(info[1].Substring(info[1].LastIndexOf('=') + 1));
if (currentVersion.CompareTo(requiredVersion) < 0)
continue; // version not good enough
if (best == null || currentVersion.CompareTo(bestVersion) < 0) {
bestVersion = currentVersion;
best = names[i];
}
}
if (best != null)
return new AssemblyName(best);
}
// use assembly with highest version
best = names[0];
info = names[0].Split(',');
bestVersion = new Version(info[1].Substring(info[1].LastIndexOf('=') + 1));
for (int i = 1; i < names.Count; i++) {
info = names[i].Split(',');
currentVersion = new Version(info[1].Substring(info[1].LastIndexOf('=') + 1));
if (currentVersion.CompareTo(bestVersion) > 0) {
bestVersion = currentVersion;
best = names[i];
}
}
return new AssemblyName(best);
}
public static Assembly LoadGACAssembly(string partialName, bool reflectionOnly)

Loading…
Cancel
Save