Permalink
Browse files

Merge branch 'hotfix/vs-updates'

  • Loading branch information...
2 parents ef17aae + 481ffb2 commit 0df9fa17ec137d686eed3c510753d80feb3a5f62 @cwensley cwensley committed Oct 13, 2016
@@ -9,6 +9,7 @@
using Eto.Wpf.Forms.Controls;
using sw = System.Windows;
using swc = System.Windows.Controls;
+using System.Windows.Threading;
[assembly: PlatformInitializerAttribute(typeof(Eto.Addin.VisualStudio.Editor.PlatformInitializer))]
@@ -58,6 +59,11 @@ public Control FromContract(object contract)
view.Focusable = false; // otherwise editor loses focus when switching back to its tab.. may be a better way around this.
return new Control(new NativeControl(view));
}
+
+ public void Unload()
+ {
+ Dispatcher.CurrentDispatcher.InvokeShutdown();
+ }
}
}
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
- <Identity Id="Eto.Addin.VisualStudio" Version="2.3.0.6" Language="en-US" Publisher="Curtis Wensley" />
+ <Identity Id="Eto.Addin.VisualStudio" Version="2.3.0.13" Language="en-US" Publisher="Curtis Wensley" />
<DisplayName>Eto.Forms Visual Studio Addin</DisplayName>
<Description xml:space="preserve">Eto.Forms Support for Visual Studio. Eto.Forms is a cross platform GUI framework for desktop and mobile applications in .NET that can target Wpf, WinForms, Direct2D, MonoMac, Xamarin.Mac, Gtk2, Gtk3, and iOS with a single codebase.</Description>
<MoreInfo>https://github.com/picoe/Eto</MoreInfo>
@@ -1,9 +1,12 @@
using Eto.Forms;
using System;
using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
+using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
@@ -32,22 +35,44 @@ public void Init(string platformType, string initializeAssembly, string mainAsse
{
if (Platform.Instance == null)
{
- resolver = AssemblyResolver.Register(references.Union(new[] { mainAssembly, Path.GetDirectoryName(typeof(AppDomainProxy).Assembly.Location) }));
+ var refs = new[] { Path.GetDirectoryName(typeof(AppDomainProxy).Assembly.Location), mainAssembly };
+ resolver = AssemblyResolver.Register(refs.Union(references));
var plat = Activator.CreateInstance(Type.GetType(platformType)) as Platform;
Platform.Initialize(plat);
if (!string.IsNullOrEmpty(initializeAssembly))
{
plat.LoadAssembly(initializeAssembly);
}
- new Application().Attach();
+ var app = new Application();
+ app.Attach();
+ app.Terminating += App_Terminating;
+
+ app.UnhandledException += App_UnhandledException;
+
+ AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
}
designPanel = new DesignPanel();
designPanel.MainAssembly = mainAssembly;
designPanel.References = references.ToList();
}
+ void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
+ {
+ // error!
+ }
+
+ void App_Terminating(object sender, CancelEventArgs e)
+ {
+ e.Cancel = true;
+ }
+
+ void CurrentDomain_DomainUnload(object sender, EventArgs e)
+ {
+ EtoAdapter.Unload();
+ }
+
Control container;
public object GetContainer()
{
@@ -75,6 +100,16 @@ public string GetCodeFile(string fileName)
{
return designPanel.GetCodeFile(fileName);
}
+
+ public void Dispose()
+ {
+ designPanel.Dispose();
+ }
+
+ public override object InitializeLifetimeService()
+ {
+ return null;
+ }
}
class AppDomainEventSink : MarshalByRefObject
@@ -90,8 +125,12 @@ public void Error(Exception ex)
{
Host.Error?.Invoke(ex);
}
- }
+ public override object InitializeLifetimeService()
+ {
+ return null;
+ }
+ }
public class AppDomainDesignHost : IDesignHost, IDisposable
{
@@ -142,12 +181,14 @@ void Timer_Elapsed(object sender, EventArgs e)
IEnumerable<string> GetShadowCopyDirs()
{
- yield return Path.GetDirectoryName(MainAssembly);
+ if (!string.IsNullOrEmpty(MainAssembly))
+ yield return Path.GetDirectoryName(MainAssembly);
if (References != null)
{
foreach (var r in References)
{
- yield return Path.GetDirectoryName(r);
+ if (!string.IsNullOrEmpty(r))
+ yield return Path.GetDirectoryName(r);
}
}
}
@@ -175,11 +216,13 @@ bool SetupAppDomain(bool setBuilder)
ShadowCopyFiles = "true",
ShadowCopyDirectories = shadowCopyDirs,
+ CachePath = Path.Combine(Path.GetDirectoryName(MainAssembly), "Eto.Designer"),
LoaderOptimization = LoaderOptimization.MultiDomain,
//LoaderOptimization = LoaderOptimization.NotSpecified
};
+ proxy = null;
domain = AppDomain.CreateDomain("eto.designer." + domainCount++, null, setup);
try
{
@@ -191,6 +234,7 @@ bool SetupAppDomain(bool setBuilder)
throw new InvalidOperationException($"Could not create proxy for domain\nApplicationBase: {AppDomain.CurrentDomain.BaseDirectory}\nBaseDir: {baseDir}\nShadowCopyDirs: {shadowCopyDirs}");
}
proxy.Init(Platform.Instance.GetType().AssemblyQualifiedName, initializeAssembly, MainAssembly, references);
+ domain.DomainUnload += Domain_DomainUnload;
proxy.ControlCreated = eventSink.ControlCreated;
proxy.Error = eventSink.Error;
@@ -203,19 +247,26 @@ bool SetupAppDomain(bool setBuilder)
{
UnloadDomain(domain);
domain = null;
+ proxy = null;
throw new InvalidOperationException($"Could not set up proxy for domain: {ex.GetBaseException().Message}", ex);
}
if (watcher == null && !string.IsNullOrEmpty(MainAssembly))
{
watcher = new FileSystemWatcher(Path.GetDirectoryName(MainAssembly), "*.dll");
watcher.Changed += (sender, e) => Application.Instance.AsyncInvoke(() => timer.Start());
+ watcher.Created += (sender, e) => Application.Instance.AsyncInvoke(() => timer.Start());
watcher.EnableRaisingEvents = true;
}
return true;
}
+ static void Domain_DomainUnload(object sender, EventArgs e)
+ {
+ Debug.WriteLine("Unloaded");
+ }
+
public Action ContainerChanged { get; set; }
public Action ControlCreated { get; set; }
@@ -272,8 +323,10 @@ protected virtual void Dispose(bool disposing)
{
if (disposing)
{
+ proxy?.Dispose();
UnloadDomain(domain);
domain = null;
+ proxy = null;
}
}
}
@@ -41,7 +41,7 @@ Assembly Resolve(object sender, ResolveEventArgs args)
foreach (var path in Files)
{
var filePath = Path.GetFileNameWithoutExtension(path);
- if (filePath == assemblyName && File.Exists(path))
+ if (string.Equals(filePath, assemblyName, StringComparison.OrdinalIgnoreCase) && File.Exists(path))
return Assembly.LoadFrom(path);
if (!Directory.Exists(path))
continue;
@@ -52,21 +52,36 @@ public class CompileResult
public IEnumerable<string> Errors { get; set; }
}
- protected abstract CompileResult Compile(string outputFile, string mainAssembly, IEnumerable<string> references, string code, out Assembly generatedAssembly);
+ protected abstract CompileResult Compile(string outputFile, IEnumerable<string> references, string code, out Assembly generatedAssembly);
- public void Create(string text, string mainAssembly, IEnumerable<string> references, Action<Control> controlCreated, Action<Exception> error)
+ class BuildToken : IBuildToken
+ {
+ public bool IsCancelled { get; set; }
+ public void Cancel()
+ {
+ IsCancelled = true;
+ }
+ }
+ public IBuildToken Create(string text, string mainAssembly, IEnumerable<string> references, Action<Control> controlCreated, Action<Exception> error)
{
RemoveOutput();
+ var token = new BuildToken();
+
+ var refs = references?.ToList() ?? new List<string>();
+ // ensure we use the built-in version of Eto, not the one used by the project
+ if (!string.IsNullOrEmpty(mainAssembly))
+ refs.Insert(0, mainAssembly);
+ refs.RemoveAll(r => Path.GetFileName(r).ToLowerInvariant() == "eto.dll");
+ refs.Add(typeof(Control).Assembly.Location);
- references = references?.ToList();
ThreadPool.QueueUserWorkItem(state =>
{
try
{
Assembly generatedAssembly;
//output = Path.Combine(Path.GetTempPath(), "EtoDesigner", Path.GetRandomFileName() + ".dll");
- var result = Compile(null, mainAssembly, references, text, out generatedAssembly);
+ var result = Compile(null, refs, text, out generatedAssembly);
if (result.Success)
{
Application.Instance.Invoke(() =>
@@ -76,28 +91,36 @@ public void Create(string text, string mainAssembly, IEnumerable<string> referen
var type = FindControlType(generatedAssembly);
var control = InstantiateControl(type);
+ if (token.IsCancelled)
+ return;
+
if (control != null)
controlCreated(control);
else
error(new FormatException("Could not find control. Make sure you have a single class derived from Control."));
}
catch (Exception ex)
{
- error(ex);
+ if (!token.IsCancelled)
+ error(ex);
}
});
}
else
{
var errorText = string.Join("\n", result.Errors);
- Application.Instance.Invoke(() => error(new FormatException(string.Format("Compile error: {0}", errorText))));
+
+ if (!token.IsCancelled)
+ Application.Instance.Invoke(() => error(new FormatException(string.Format("Compile error: {0}", errorText))));
}
}
catch (Exception ex)
{
- Application.Instance.Invoke(() => error(ex));
+ if (!token.IsCancelled)
+ Application.Instance.Invoke(() => error(ex));
}
});
+ return token;
}
@@ -137,11 +160,23 @@ protected string GetReferenceAssembliesFolder()
return referenceDir;
}
+ public static IEnumerable<Type> GetLoadableTypes(Assembly assembly)
+ {
+ try
+ {
+ return assembly.GetTypes();
+ }
+ catch (ReflectionTypeLoadException e)
+ {
+ return e.Types.Where(t => t != null);
+ }
+ }
+
public static Type FindControlType(Assembly assembly)
{
if (assembly == null)
return null;
- return assembly.GetTypes().FirstOrDefault(t => typeof(Control).IsAssignableFrom(t));
+ return GetLoadableTypes(assembly).FirstOrDefault(t => typeof(Control).IsAssignableFrom(t));
}
@@ -64,7 +64,7 @@ static void FixMonoPath()
}
}
- protected override CompileResult Compile(string outputFile, string mainAssembly, IEnumerable<string> references, string code, out Assembly generatedAssembly)
+ protected override CompileResult Compile(string outputFile, IEnumerable<string> references, string code, out Assembly generatedAssembly)
{
var inMemory = string.IsNullOrEmpty(outputFile);
var parameters = new CompilerParameters
@@ -79,8 +79,6 @@ protected override CompileResult Compile(string outputFile, string mainAssembly,
SetParameters(parameters);
- if (!string.IsNullOrEmpty(mainAssembly) && File.Exists(mainAssembly))
- parameters.ReferencedAssemblies.Add(mainAssembly);
if (references != null)
{
foreach (var reference in references)
@@ -11,7 +11,7 @@ namespace Eto.Designer.Builders
{
public class JsonInterfaceBuilder : IInterfaceBuilder
{
- public void Create(string text, string mainAssembly, IEnumerable<string> references, Action<Forms.Control> controlCreated, Action<Exception> error)
+ public IBuildToken Create(string text, string mainAssembly, IEnumerable<string> references, Action<Forms.Control> controlCreated, Action<Exception> error)
{
try
{
@@ -27,6 +27,7 @@ public void Create(string text, string mainAssembly, IEnumerable<string> referen
{
error(ex);
}
+ return null;
}
}
}
@@ -21,7 +21,10 @@ protected override Compilation CreateCompilation(SyntaxTree syntaxTree, string a
assemblyName,
syntaxTrees: new[] { syntaxTree },
references: references,
- options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
+ options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary,
+ assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default
+ )
+ );
}
}
}
@@ -38,15 +38,13 @@ protected virtual IEnumerable<string> GetReferences()
protected abstract SyntaxTree ParseText(string code);
- protected override CompileResult Compile(string outputFile, string mainAssembly, IEnumerable<string> references, string code, out Assembly generatedAssembly)
+ protected override CompileResult Compile(string outputFile, IEnumerable<string> references, string code, out Assembly generatedAssembly)
{
var syntaxTree = ParseText(code);
string assemblyName = Path.GetRandomFileName();
var refMetadata = GetReferences().Select(r => MetadataReference.CreateFromFile(r)).ToList();
- if (!string.IsNullOrEmpty(mainAssembly) && File.Exists(mainAssembly))
- refMetadata.Add(MetadataReference.CreateFromFile(mainAssembly));
if (references != null)
{
foreach (var reference in references)
@@ -12,7 +12,7 @@ namespace Eto.Designer.Builders
{
public class XamlInterfaceBuilder : IInterfaceBuilder
{
- public void Create(string text, string mainAssembly, IEnumerable<string> references, Action<Control> controlCreated, Action<Exception> error)
+ public IBuildToken Create(string text, string mainAssembly, IEnumerable<string> references, Action<Control> controlCreated, Action<Exception> error)
{
var oldDesignMode = XamlReader.DesignMode;
XamlReader.DesignMode = true;
@@ -34,6 +34,7 @@ public void Create(string text, string mainAssembly, IEnumerable<string> referen
{
XamlReader.DesignMode = oldDesignMode;
}
+ return null;
}
}
}
Oops, something went wrong.

0 comments on commit 0df9fa1

Please sign in to comment.