Browse Source
Several important classes are not ported to SD5 yet and are commented out; so the designer is not yet usable.pull/32/merge
36 changed files with 375 additions and 828 deletions
@ -1,588 +0,0 @@
@@ -1,588 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.ComponentModel.Design; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using Microsoft.Win32; |
||||
|
||||
namespace ICSharpCode.FormsDesigner.Services |
||||
{ |
||||
public class TypeResolutionService : ITypeResolutionService |
||||
{ |
||||
readonly static List<Assembly> designerAssemblies = new List<Assembly>(); |
||||
// hash of file content -> Assembly
|
||||
readonly static Dictionary<string, Assembly> assemblyDict = new Dictionary<string, Assembly>(); |
||||
|
||||
/// <summary>
|
||||
/// List of assemblies used by the form designer. This static list is not an optimal solution,
|
||||
/// but better than using AppDomain.CurrentDomain.GetAssemblies(). See SD2-630.
|
||||
/// </summary>
|
||||
public static List<Assembly> DesignerAssemblies { |
||||
get { |
||||
return designerAssemblies; |
||||
} |
||||
} |
||||
|
||||
static TypeResolutionService() |
||||
{ |
||||
ClearMixedAssembliesTemporaryFiles(); |
||||
DesignerAssemblies.Add(ProjectContentRegistry.MscorlibAssembly); |
||||
DesignerAssemblies.Add(ProjectContentRegistry.SystemAssembly); |
||||
DesignerAssemblies.Add(typeof(System.Drawing.Point).Assembly); |
||||
DesignerAssemblies.Add(typeof(System.Windows.Forms.Design.AnchorEditor).Assembly); |
||||
RegisterVSDesignerWorkaround(); |
||||
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolveEventHandler; |
||||
|
||||
} |
||||
|
||||
[System.Runtime.InteropServices.DllImport("kernel32.dll")] |
||||
private static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags); |
||||
const int MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004; |
||||
|
||||
static void MarkFileToDeleteOnReboot(string fileName) |
||||
{ |
||||
MoveFileEx(fileName, null, MOVEFILE_DELAY_UNTIL_REBOOT); |
||||
} |
||||
|
||||
static void ClearMixedAssembliesTemporaryFiles() |
||||
{ |
||||
string[] files = Directory.GetFiles(Path.GetTempPath(), "*.sd_forms_designer_mixed_assembly.dll"); |
||||
foreach (string fileName in files) { |
||||
try { |
||||
File.Delete(fileName); |
||||
} catch {} |
||||
} |
||||
/* We don't need to debug controls inside the forms designer |
||||
files = Directory.GetFiles(Path.GetTempPath(), "*.pdb"); |
||||
foreach (string fileName in files) { |
||||
try { |
||||
File.Delete(fileName); |
||||
} catch {} |
||||
}*/ |
||||
} |
||||
|
||||
|
||||
string formSourceFileName; |
||||
IProject callingProject; |
||||
/// <summary>
|
||||
/// Dictionary of file name -> hash of loaded assemblies for the currently designed document.
|
||||
/// Used to detect changes in references assemblies.
|
||||
/// </summary>
|
||||
readonly Dictionary<string, string> loadedAssembliesForCurrentDocument = new Dictionary<string, string>(StringComparer.Ordinal); |
||||
|
||||
/// <summary>
|
||||
/// Gets the project content of the project that created this TypeResolutionService.
|
||||
/// Returns null when no calling project was specified.
|
||||
/// </summary>
|
||||
public IProject CallingProject { |
||||
get { |
||||
if (formSourceFileName != null) { |
||||
if (ProjectService.OpenSolution != null) { |
||||
IProject p = ProjectService.OpenSolution.FindProjectContainingFile(formSourceFileName); |
||||
if (p != null) { |
||||
callingProject = ParserService.GetProjectContent(p); |
||||
} |
||||
} |
||||
formSourceFileName = null; |
||||
} |
||||
return callingProject; |
||||
} |
||||
} |
||||
|
||||
public TypeResolutionService() |
||||
{ |
||||
} |
||||
|
||||
public TypeResolutionService(string formSourceFileName) |
||||
{ |
||||
this.formSourceFileName = formSourceFileName; |
||||
} |
||||
|
||||
readonly HashSet<IProject> projectContentsCurrentlyLoadingAssembly = new HashSet<IProjectContent>(); |
||||
|
||||
/// <summary>
|
||||
/// Loads the assembly represented by the project content. Returns null on failure.
|
||||
/// </summary>
|
||||
public Assembly LoadAssembly(IProject pc) |
||||
{ |
||||
WorkbenchSingleton.AssertMainThread(); |
||||
// prevent StackOverflow when project contents have cyclic dependencies
|
||||
// Very popular example of cyclic dependency: System <-> System.Xml
|
||||
if (!projectContentsCurrentlyLoadingAssembly.Add(pc)) |
||||
return null; |
||||
|
||||
Assembly sdAssembly; |
||||
if (IsSharpDevelopAssembly(pc, out sdAssembly)) |
||||
return sdAssembly; |
||||
|
||||
try { |
||||
// load dependencies of current assembly
|
||||
foreach (IProjectContent rpc in pc.ThreadSafeGetReferencedContents()) { |
||||
if (rpc is ParseProjectContent) { |
||||
LoadAssembly(rpc); |
||||
} else if (rpc is ReflectionProjectContent) { |
||||
ReflectionProjectContent rrpc = (ReflectionProjectContent)rpc; |
||||
if (!rrpc.IsGacAssembly) { |
||||
LoadAssembly(rpc); |
||||
} |
||||
} |
||||
} |
||||
} finally { |
||||
projectContentsCurrentlyLoadingAssembly.Remove(pc); |
||||
} |
||||
|
||||
if (pc.Project != null) { |
||||
return LoadAssembly(((IProject)pc.Project).OutputAssemblyFullPath); |
||||
} else if (pc is ReflectionProjectContent) { |
||||
ReflectionProjectContent rpc = (ReflectionProjectContent)pc; |
||||
if (rpc.IsGacAssembly) |
||||
return LoadAssembly(new AssemblyName(rpc.AssemblyFullName), false); |
||||
else |
||||
return LoadAssembly(rpc.AssemblyLocation); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
readonly string sharpDevelopRoot = Directory.GetParent(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)).FullName; |
||||
|
||||
bool IsSharpDevelopAssembly(IUnresolvedAssembly pc, out Assembly assembly) |
||||
{ |
||||
assembly = null; |
||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { |
||||
if (!asm.IsDynamic && asm.Location.StartsWith(sharpDevelopRoot, StringComparison.OrdinalIgnoreCase) && pc.AssemblyName == asm.GetName().Name) { |
||||
assembly = asm; |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
static string GetHash(string fileName) |
||||
{ |
||||
return Path.GetFileName(fileName).ToLowerInvariant() + File.GetLastWriteTimeUtc(fileName).Ticks.ToString(); |
||||
} |
||||
|
||||
static string GetOriginalAssemblyFullPath(Assembly asm) |
||||
{ |
||||
if (asm == null) throw new ArgumentNullException("asm"); |
||||
try { |
||||
return new Uri(asm.CodeBase, UriKind.Absolute).LocalPath; |
||||
} catch (UriFormatException ex) { |
||||
LoggingService.Warn("Could not determine path for assembly '" + asm.ToString() + "', CodeBase='" + asm.CodeBase + "': " + ex.Message); |
||||
return asm.Location; |
||||
} catch (InvalidOperationException ex) { |
||||
LoggingService.Warn("Could not determine path for assembly '" + asm.ToString() + "', CodeBase='" + asm.CodeBase + "': " + ex.Message); |
||||
return asm.Location; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Loads the file in none-locking mode. Returns null on failure.
|
||||
/// </summary>
|
||||
public Assembly LoadAssembly(string fileName) |
||||
{ |
||||
if (!File.Exists(fileName)) |
||||
return null; |
||||
|
||||
// FIX for SD2-716, remove when designer gets its own AppDomain
|
||||
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { |
||||
try { |
||||
if (string.Equals(GetOriginalAssemblyFullPath(asm), fileName, StringComparison.OrdinalIgnoreCase)) { |
||||
RegisterAssembly(asm); |
||||
return asm; |
||||
} |
||||
} catch (NotSupportedException) { |
||||
// Fixes forum-12823
|
||||
} |
||||
} |
||||
|
||||
string hash = GetHash(fileName); |
||||
lock (assemblyDict) { |
||||
Assembly asm; |
||||
if (assemblyDict.TryGetValue(hash, out asm)) |
||||
return asm; |
||||
LoggingService.Debug("Loading assembly " + fileName + " (hash " + hash + ")"); |
||||
try { |
||||
asm = Assembly.Load(File.ReadAllBytes(fileName)); |
||||
} catch (BadImageFormatException e) { |
||||
if (e.Message.Contains("HRESULT: 0x8013141D")) { |
||||
LoggingService.Debug("Get HRESULt 0x8013141D, loading netmodule"); |
||||
//netmodule
|
||||
string tempPath = Path.GetTempFileName(); |
||||
File.Delete(tempPath); |
||||
tempPath += ".sd_forms_designer_netmodule_assembly.dll"; |
||||
|
||||
try { |
||||
//convert netmodule to assembly
|
||||
Process p = new Process(); |
||||
p.StartInfo.UseShellExecute = false; |
||||
p.StartInfo.FileName = Path.GetDirectoryName(typeof(object).Module.FullyQualifiedName) + Path.DirectorySeparatorChar + "al.exe"; |
||||
p.StartInfo.Arguments = "\"" + fileName +"\" /out:\"" + tempPath + "\""; |
||||
p.StartInfo.CreateNoWindow = true; |
||||
p.Start(); |
||||
p.WaitForExit(); |
||||
|
||||
if(p.ExitCode == 0 && File.Exists(tempPath)) { |
||||
byte[] asm_data = File.ReadAllBytes(tempPath); |
||||
asm = Assembly.Load(asm_data); |
||||
asm.LoadModule(Path.GetFileName(fileName), File.ReadAllBytes(fileName)); |
||||
} |
||||
} catch (Exception ex) { |
||||
MessageService.ShowException(ex, "Error calling linker for netmodule"); |
||||
} |
||||
try { |
||||
File.Delete(tempPath); |
||||
} catch {} |
||||
} else { |
||||
// Show other load errors in the compiler message view,
|
||||
// but do not prevent the designer from loading.
|
||||
// The error might be caused by an assembly that is
|
||||
// not even needed for the designer to load.
|
||||
LoggingService.Error("Error loading assembly " + fileName, e); |
||||
WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView)).BringPadToFront(); |
||||
TaskService.BuildMessageViewCategory.AppendText( |
||||
StringParser.Parse("${res:FileUtilityService.ErrorWhileLoading}") |
||||
+ "\r\n" + fileName + "\r\n" + e.Message + "\r\n" |
||||
); |
||||
return null; |
||||
} |
||||
} catch (FileLoadException e) { |
||||
if (e.Message.Contains("HRESULT: 0x80131402")) { |
||||
LoggingService.Debug("Get HRESULt 0x80131402, loading mixed modes asm from disk"); |
||||
//this is C++/CLI Mixed assembly which can only be loaded from disk, not in-memory
|
||||
string tempPath = Path.GetTempFileName(); |
||||
File.Delete(tempPath); |
||||
tempPath += ".sd_forms_designer_mixed_assembly.dll"; |
||||
File.Copy(fileName, tempPath); |
||||
|
||||
/* We don't need to debug controls inside the forms designer |
||||
string pdbpath = Path.GetDirectoryName(fileName) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(fileName) + ".pdb"; |
||||
if (File.Exists(pdbpath)) { |
||||
string newpdbpath = Path.GetTempPath() + Path.DirectorySeparatorChar + Path.GetFileName(pdbpath); |
||||
try { |
||||
File.Copy(pdbpath, newpdbpath); |
||||
MarkFileToDeleteOnReboot(newpdbpath); |
||||
} catch { |
||||
} |
||||
} |
||||
*/ |
||||
asm = Assembly.LoadFile(tempPath); |
||||
MarkFileToDeleteOnReboot(tempPath); |
||||
} else if (e.Message.Contains("HRESULT: 0x80131019")) { |
||||
LoggingService.Debug(e.Message); |
||||
LoggingService.Debug("Attempting to load unverifiable assembly. Ignoring."); |
||||
return null; |
||||
} else { |
||||
throw; // don't ignore other load errors
|
||||
} |
||||
} |
||||
|
||||
lock (designerAssemblies) { |
||||
if (!designerAssemblies.Contains(asm)) |
||||
designerAssemblies.Insert(0, asm); |
||||
} |
||||
lock (this.loadedAssembliesForCurrentDocument) { |
||||
this.loadedAssembliesForCurrentDocument[fileName] = hash; |
||||
} |
||||
assemblyDict[hash] = asm; |
||||
return asm; |
||||
} |
||||
} |
||||
|
||||
void RegisterAssembly(Assembly asm) |
||||
{ |
||||
string file = GetOriginalAssemblyFullPath(asm); |
||||
if (!String.IsNullOrEmpty(file)) { |
||||
string hash = GetHash(file); |
||||
lock (assemblyDict) { |
||||
assemblyDict[hash] = asm; |
||||
} |
||||
lock (this.loadedAssembliesForCurrentDocument) { |
||||
this.loadedAssembliesForCurrentDocument[file] = hash; |
||||
} |
||||
} |
||||
lock (designerAssemblies) { |
||||
if (!designerAssemblies.Contains(asm)) |
||||
designerAssemblies.Insert(0, asm); |
||||
} |
||||
} |
||||
|
||||
public Assembly GetAssembly(AssemblyName name) |
||||
{ |
||||
return LoadAssembly(name, false); |
||||
} |
||||
|
||||
public Assembly GetAssembly(AssemblyName name, bool throwOnError) |
||||
{ |
||||
return LoadAssembly(name, throwOnError); |
||||
} |
||||
|
||||
Assembly LoadAssembly(AssemblyName name, bool throwOnError) |
||||
{ |
||||
try { |
||||
Assembly asm = Assembly.Load(name); |
||||
RegisterAssembly(asm); |
||||
return asm; |
||||
} catch (System.IO.FileLoadException) { |
||||
if (throwOnError) |
||||
throw; |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public string GetPathOfAssembly(AssemblyName name) |
||||
{ |
||||
Assembly assembly = GetAssembly(name); |
||||
if (assembly != null) { |
||||
return GetOriginalAssemblyFullPath(assembly); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public Type GetType(string name) |
||||
{ |
||||
return GetType(name, false, false); |
||||
} |
||||
|
||||
public Type GetType(string name, bool throwOnError) |
||||
{ |
||||
return GetType(name, throwOnError, false); |
||||
} |
||||
|
||||
#if DEBUG
|
||||
int count = 0; |
||||
#endif
|
||||
|
||||
Dictionary<string, Type> typeCache = new Dictionary<string, Type>(StringComparer.Ordinal); |
||||
Dictionary<string, Type> typeCacheIgnoreCase = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase); |
||||
|
||||
public void ClearCaches() |
||||
{ |
||||
typeCacheIgnoreCase.Clear(); |
||||
typeCache.Clear(); |
||||
} |
||||
|
||||
public Type GetType(string name, bool throwOnError, bool ignoreCase) |
||||
{ |
||||
if (name == null || name.Length == 0) { |
||||
return null; |
||||
} |
||||
if (IgnoreType(name)) { |
||||
return null; |
||||
} |
||||
if (ignoreCase) { |
||||
Type cachedType; |
||||
if (typeCacheIgnoreCase.TryGetValue(name, out cachedType)) |
||||
return cachedType; |
||||
} else { |
||||
Type cachedType; |
||||
if (typeCache.TryGetValue(name, out cachedType)) |
||||
return cachedType; |
||||
} |
||||
#if DEBUG
|
||||
if (!name.StartsWith("System.")) { |
||||
count++; |
||||
LoggingService.Debug(count + " TypeResolutionService: Looking for " + name); |
||||
} |
||||
#endif
|
||||
try { |
||||
|
||||
Type type = Type.GetType(name, false, ignoreCase); |
||||
|
||||
if (type == null) { |
||||
IProjectContent pc = this.CallingProject; |
||||
if (pc != null) { |
||||
// find assembly containing type by using SharpDevelop.Dom
|
||||
IClass foundClass; |
||||
if (name.Contains("`")) { |
||||
int typeParameterCount; |
||||
int.TryParse(name.Substring(name.IndexOf('`') + 1), out typeParameterCount); |
||||
foundClass = pc.GetClass(name.Substring(0, name.IndexOf('`')).Replace('+', '.'), typeParameterCount); |
||||
} else { |
||||
foundClass = pc.GetClass(name.Replace('+', '.'), 0); |
||||
} |
||||
if (foundClass != null) { |
||||
Assembly assembly = LoadAssembly(foundClass.ProjectContent); |
||||
if (assembly != null) { |
||||
type = assembly.GetType(name, false, ignoreCase); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// type lookup for typename, assembly, xyz style lookups
|
||||
if (type == null) { |
||||
int idx = name.IndexOf(","); |
||||
if (idx > 0) { |
||||
string[] splitName = name.Split(','); |
||||
string typeName = splitName[0]; |
||||
string assemblyName = splitName[1].Substring(1); |
||||
Assembly assembly = null; |
||||
try { |
||||
assembly = Assembly.Load(assemblyName); |
||||
} catch (Exception e) { |
||||
LoggingService.Error(e); |
||||
} |
||||
if (assembly != null) { |
||||
string fileName = GetOriginalAssemblyFullPath(assembly); |
||||
if (!String.IsNullOrEmpty(fileName)) { |
||||
lock (this.loadedAssembliesForCurrentDocument) { |
||||
this.loadedAssembliesForCurrentDocument[fileName] = GetHash(fileName); |
||||
} |
||||
} |
||||
lock (designerAssemblies) { |
||||
if (!designerAssemblies.Contains(assembly)) |
||||
designerAssemblies.Add(assembly); |
||||
} |
||||
type = assembly.GetType(typeName, false, ignoreCase); |
||||
} else { |
||||
type = Type.GetType(typeName, false, ignoreCase); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (type == null) { |
||||
lock (designerAssemblies) { |
||||
foreach (Assembly asm in DesignerAssemblies) { |
||||
try { |
||||
Type t = asm.GetType(name, false); |
||||
if (t != null) { |
||||
AddToCache(name, t, ignoreCase); |
||||
return t; |
||||
} |
||||
} catch (FileNotFoundException) { |
||||
} catch (FileLoadException) { |
||||
} catch (BadImageFormatException) { |
||||
// ignore assembly load errors
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (throwOnError && type == null) |
||||
throw new TypeLoadException(name + " not found by TypeResolutionService"); |
||||
AddToCache(name, type, ignoreCase); |
||||
return type; |
||||
} catch (Exception e) { |
||||
LoggingService.Error(e); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
void AddToCache(string name, Type type, bool ignoreCase) |
||||
{ |
||||
if (type == null) |
||||
return; |
||||
if (ignoreCase) { |
||||
typeCacheIgnoreCase.Add(name, type); |
||||
} else { |
||||
typeCache.Add(name, type); |
||||
} |
||||
} |
||||
|
||||
public void ReferenceAssembly(AssemblyName name) |
||||
{ |
||||
ICSharpCode.Core.LoggingService.Warn("TODO: Add Assembly reference : " + name); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets whether an assembly referenced by the currently designed document
|
||||
/// has been changed since it has been loaded.
|
||||
/// </summary>
|
||||
public bool ReferencedAssemblyChanged { |
||||
get { |
||||
return this.loadedAssembliesForCurrentDocument.Any( |
||||
pair => !File.Exists(pair.Key) || !String.Equals(pair.Value, GetHash(pair.Key), StringComparison.Ordinal) |
||||
); |
||||
} |
||||
} |
||||
|
||||
#region VSDesigner workarounds
|
||||
/// <summary>
|
||||
/// HACK - Ignore any requests for types from the Microsoft.VSDesigner
|
||||
/// assembly. There are smart tag problems if data adapter
|
||||
/// designers are used from this assembly.
|
||||
/// </summary>
|
||||
bool IgnoreType(string name) |
||||
{ |
||||
int idx = name.IndexOf(","); |
||||
if (idx > 0) { |
||||
string[] splitName = name.Split(','); |
||||
string assemblyName = splitName[1].Substring(1); |
||||
if (assemblyName == "Microsoft.VSDesigner") { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
static string vsDesignerIdeDir; |
||||
|
||||
static void RegisterVSDesignerWorkaround() |
||||
{ |
||||
if (vsDesignerIdeDir == null) { |
||||
vsDesignerIdeDir = ""; |
||||
try { |
||||
using(RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\VisualStudio\8.0\Setup\VS")) { |
||||
if (key != null) { |
||||
vsDesignerIdeDir = key.GetValue("VS7CommonDir") as string ?? ""; |
||||
} |
||||
} |
||||
} catch (System.Security.SecurityException) { |
||||
// registry access might be denied
|
||||
} |
||||
if (vsDesignerIdeDir.Length > 0) { |
||||
vsDesignerIdeDir = Path.Combine(vsDesignerIdeDir, "IDE"); |
||||
AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args) { |
||||
string shortName = args.Name; |
||||
if (shortName.IndexOf(',') >= 0) { |
||||
shortName = shortName.Substring(0, shortName.IndexOf(',')); |
||||
} |
||||
if (shortName.StartsWith("Microsoft.") |
||||
&& File.Exists(Path.Combine(vsDesignerIdeDir, shortName + ".dll"))) |
||||
{ |
||||
return Assembly.LoadFrom(Path.Combine(vsDesignerIdeDir, shortName + ".dll")); |
||||
} |
||||
return null; |
||||
}; |
||||
} |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
static Assembly AssemblyResolveEventHandler(object sender, ResolveEventArgs args) |
||||
{ |
||||
LoggingService.Debug("TypeResolutionService: AssemblyResolveEventHandler: " + args.Name); |
||||
|
||||
Assembly lastAssembly = null; |
||||
|
||||
foreach (Assembly asm in TypeResolutionService.DesignerAssemblies) { |
||||
if (asm.FullName == args.Name) { |
||||
return asm; |
||||
} |
||||
} |
||||
|
||||
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { |
||||
if (asm.FullName == args.Name) { |
||||
lastAssembly = asm; |
||||
} |
||||
} |
||||
if (lastAssembly != null) { |
||||
TypeResolutionService.DesignerAssemblies.Add(lastAssembly); |
||||
LoggingService.Info("ICSharpAssemblyResolver found..." + args.Name); |
||||
} |
||||
return lastAssembly; |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue