diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs index d0f7b82e92..c7e2cfc624 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs @@ -77,9 +77,7 @@ namespace ICSharpCode.FormsDesigner.Gui ReflectionProjectContent rpc = pc as ReflectionProjectContent; if (rpc == null) continue; - if (rpc.AssemblyFullName == typeof(object).Assembly.FullName) - continue; - if (GacInterop.IsWithinGac(rpc.AssemblyLocation)) + if (rpc.IsGacAssembly) continue; } foreach (IClass c in pc.Classes) { diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs index 889eeea69c..7862e938c0 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs @@ -109,18 +109,18 @@ namespace ICSharpCode.FormsDesigner.Services this.formSourceFileName = formSourceFileName; } - static readonly Dictionary projectContentsCurrentlyLoadingAssembly = new Dictionary(); + readonly HashSet projectContentsCurrentlyLoadingAssembly = new HashSet(); /// /// Loads the assembly represented by the project content. Returns null on failure. /// public Assembly LoadAssembly(IProjectContent pc) { + WorkbenchSingleton.AssertMainThread(); // prevent StackOverflow when project contents have cyclic dependencies - // Very popular example of cyclic dependency: System <-> System.Xml (yes, really!) - if (projectContentsCurrentlyLoadingAssembly.ContainsKey(pc)) + // Very popular example of cyclic dependency: System <-> System.Xml + if (!projectContentsCurrentlyLoadingAssembly.Add(pc)) return null; - projectContentsCurrentlyLoadingAssembly.Add(pc, null); try { // load dependencies of current assembly @@ -129,9 +129,7 @@ namespace ICSharpCode.FormsDesigner.Services LoadAssembly(rpc); } else if (rpc is ReflectionProjectContent) { ReflectionProjectContent rrpc = (ReflectionProjectContent)rpc; - if (rrpc.AssemblyFullName != typeof(object).FullName - && !GacInterop.IsWithinGac(rrpc.AssemblyLocation)) - { + if (!rrpc.IsGacAssembly) { LoadAssembly(rpc); } } @@ -144,7 +142,7 @@ namespace ICSharpCode.FormsDesigner.Services return LoadAssembly(((IProject)pc.Project).OutputAssemblyFullPath); } else if (pc is ReflectionProjectContent) { ReflectionProjectContent rpc = (ReflectionProjectContent)pc; - if (GacInterop.IsWithinGac(rpc.AssemblyLocation)) + if (rpc.IsGacAssembly) return LoadAssembly(new AssemblyName(rpc.AssemblyFullName), false); else return LoadAssembly(rpc.AssemblyLocation); diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/ILSpyController.cs b/src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/ILSpyController.cs index 7bc3e20acb..28c1d2c78b 100644 --- a/src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/ILSpyController.cs +++ b/src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/ILSpyController.cs @@ -59,12 +59,7 @@ namespace ICSharpCode.ILSpyAddIn if (rpc == null) throw new ArgumentNullException("rpc"); // prefer GAC assemblies over reference assemblies: - string assemblyLocation = FindAssemblyInNetGac(new DomAssemblyName(rpc.AssemblyFullName)); - if (string.IsNullOrEmpty(assemblyLocation)) { - // use file only if assembly isn't in GAC: - assemblyLocation = rpc.AssemblyLocation; - } - return assemblyLocation; + return rpc.RealAssemblyLocation; } #region Find ILSpy @@ -103,74 +98,5 @@ namespace ICSharpCode.ILSpyAddIn return path; } #endregion - - #region FindAssemblyInGac - // This region is based on code from Mono.Cecil: - - // Author: - // Jb Evain (jbevain@gmail.com) - // - // Copyright (c) 2008 - 2010 Jb Evain - // - // Permission is hereby granted, free of charge, to any person obtaining - // a copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to - // permit persons to whom the Software is furnished to do so, subject to - // the following conditions: - // - // The above copyright notice and this permission notice shall be - // included in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - // - - static readonly string[] gac_paths = { GacInterop.GacRootPathV2, GacInterop.GacRootPathV4 }; - static readonly string[] gacs = { "GAC_MSIL", "GAC_32", "GAC" }; - static readonly string[] prefixes = { string.Empty, "v4.0_" }; - - /// - /// Gets the file name for an assembly stored in the GAC. - /// - public static string FindAssemblyInNetGac (DomAssemblyName reference) - { - // without public key, it can't be in the GAC - if (reference.PublicKeyToken == null) - return null; - - for (int i = 0; i < 2; i++) { - for (int j = 0; j < gacs.Length; j++) { - var gac = Path.Combine (gac_paths [i], gacs [j]); - var file = GetAssemblyFile (reference, prefixes [i], gac); - if (File.Exists (file)) - return file; - } - } - - return null; - } - - static string GetAssemblyFile (DomAssemblyName reference, string prefix, string gac) - { - var gac_folder = new StringBuilder () - .Append (prefix) - .Append (reference.Version) - .Append ("__"); - - gac_folder.Append (reference.PublicKeyToken); - - return Path.Combine ( - Path.Combine ( - Path.Combine (gac, reference.ShortName), gac_folder.ToString ()), - reference.ShortName + ".dll"); - } - #endregion } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/IdeChooseClassService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/IdeChooseClassService.cs index 81df571461..7714a4b85b 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/IdeChooseClassService.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/IdeChooseClassService.cs @@ -20,7 +20,7 @@ namespace ICSharpCode.WpfDesign.AddIn { var r = projectContent as ReflectionProjectContent; if (r != null) { - return r.AssemblyLocation; + return r.RealAssemblyLocation; } var p = projectContent.Project as IProject; if (p != null) { diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs index 0d7e9be796..8f14cb708f 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs @@ -3,9 +3,9 @@ using System; using System.Collections.Generic; +using System.IO; using System.Reflection; using System.Text; - using MSjogren.GacTool.FusionNative; namespace ICSharpCode.SharpDevelop.Dom @@ -16,25 +16,15 @@ namespace ICSharpCode.SharpDevelop.Dom /// public static class GacInterop { - volatile static string cachedGacPathV2; - volatile static string cachedGacPathV4; + static readonly string cachedGacPathV2 = Fusion.GetGacPath(false); + static readonly string cachedGacPathV4 = Fusion.GetGacPath(true); public static string GacRootPathV2 { - get { - if (cachedGacPathV2 == null) { - cachedGacPathV2 = Fusion.GetGacPath(false); - } - return cachedGacPathV2; - } + get { return cachedGacPathV2; } } public static string GacRootPathV4 { - get { - if (cachedGacPathV4 == null) { - cachedGacPathV4 = Fusion.GetGacPath(true); - } - return cachedGacPathV4; - } + get { return cachedGacPathV4; } } public static bool IsWithinGac(string assemblyLocation) @@ -135,5 +125,74 @@ namespace ICSharpCode.SharpDevelop.Dom } return new DomAssemblyName(best); } + + #region FindAssemblyInGac + // This region is based on code from Mono.Cecil: + + // Author: + // Jb Evain (jbevain@gmail.com) + // + // Copyright (c) 2008 - 2010 Jb Evain + // + // Permission is hereby granted, free of charge, to any person obtaining + // a copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to + // permit persons to whom the Software is furnished to do so, subject to + // the following conditions: + // + // The above copyright notice and this permission notice shall be + // included in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + // + + static readonly string[] gac_paths = { GacInterop.GacRootPathV2, GacInterop.GacRootPathV4 }; + static readonly string[] gacs = { "GAC_MSIL", "GAC_32", "GAC" }; + static readonly string[] prefixes = { string.Empty, "v4.0_" }; + + /// + /// Gets the file name for an assembly stored in the GAC. + /// + public static string FindAssemblyInNetGac (DomAssemblyName reference) + { + // without public key, it can't be in the GAC + if (reference.PublicKeyToken == null) + return null; + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < gacs.Length; j++) { + var gac = Path.Combine (gac_paths [i], gacs [j]); + var file = GetAssemblyFile (reference, prefixes [i], gac); + if (File.Exists (file)) + return file; + } + } + + return null; + } + + static string GetAssemblyFile (DomAssemblyName reference, string prefix, string gac) + { + var gac_folder = new StringBuilder () + .Append (prefix) + .Append (reference.Version) + .Append ("__"); + + gac_folder.Append (reference.PublicKeyToken); + + return Path.Combine ( + Path.Combine ( + Path.Combine (gac, reference.ShortName), gac_folder.ToString ()), + reference.ShortName + ".dll"); + } + #endregion } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ReflectionProjectContent.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ReflectionProjectContent.cs index 4896723b54..d8f192b7b5 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ReflectionProjectContent.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ReflectionProjectContent.cs @@ -19,22 +19,64 @@ namespace ICSharpCode.SharpDevelop.Dom string assemblyLocation; ProjectContentRegistry registry; + /// + /// Gets the file path to the (reference) assembly. + /// public string AssemblyLocation { get { return assemblyLocation; } } + /// + /// Gets the full assembly name (e.g. "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") + /// public string AssemblyFullName { get { return assemblyFullName; } } + /// + /// Gets the short assembly name (e.g. "System") + /// public override string AssemblyName { get { return assemblyName; } } + volatile string assemblyLocationInGAC; + + string GetAssemblyLocationInGAC() + { + if (assemblyLocationInGAC == null) { + assemblyLocationInGAC = GacInterop.FindAssemblyInNetGac(new DomAssemblyName(assemblyFullName)) ?? string.Empty; + } + return assemblyLocationInGAC; + } + + /// + /// Gets the real assembly location. + /// For reference assemblies of GAC assemblies, this is the assembly in the GAC. + /// Otherwise, this is the same as AssemblyLocation. + /// + public string RealAssemblyLocation { + get { + string gacAssembly = GetAssemblyLocationInGAC(); + if (string.IsNullOrEmpty(gacAssembly)) + return this.AssemblyLocation; + else + return gacAssembly; + } + } + + /// + /// Gets whether this assembly is available in the GAC. + /// This property also returns true for reference assemblies when the corresponding real assembly is available in the GAC. + /// + public bool IsGacAssembly { + get { return !string.IsNullOrEmpty(GetAssemblyLocationInGAC()); } + } + /// /// Gets the list of assembly names referenced by this project content. ///