From 8d0d19880877a289545062ffd9e93e0d48bc45fe Mon Sep 17 00:00:00 2001 From: Sandy Armstrong Date: Fri, 6 Jul 2018 09:00:40 -0700 Subject: [PATCH] Client: Cache global state assemblies by name 1. Open Workbooks 2. Create a XF iOS workbook 3. Create a non-XF iOS workbook The second workbook, for whatever reason, doesn't set a PEImage for the global state assembly, so the client tries to resolve it from a different location, leading to an exception. Cache to avoid this. Will be nice when this reflection loading can go away. --- .../EvaluationContextInitializeRequest.cs | 3 +++ .../Compilation/CompilationWorkspaceFactory.cs | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Agents/Xamarin.Interactive/CodeAnalysis/EvaluationContextInitializeRequest.cs b/Agents/Xamarin.Interactive/CodeAnalysis/EvaluationContextInitializeRequest.cs index 6df7f6ab9..73c342e0b 100644 --- a/Agents/Xamarin.Interactive/CodeAnalysis/EvaluationContextInitializeRequest.cs +++ b/Agents/Xamarin.Interactive/CodeAnalysis/EvaluationContextInitializeRequest.cs @@ -38,6 +38,9 @@ protected override Task HandleAsync (Agent agent var globalStateType = evaluationContext.GlobalState.GetType (); response.GlobalStateTypeName = globalStateType.FullName; + // TODO: Why is globalStateType.Assembly.Location null when you + // create a non-XF workbook after creating an XF workbook? + // HACK: This is a temporary fix to get iOS agent/app assemblies sent to the // Windows client when using the remote sim. var peImage = IncludePeImage && File.Exists (globalStateType.Assembly.Location) diff --git a/Clients/Xamarin.Interactive.Client/Compilation/CompilationWorkspaceFactory.cs b/Clients/Xamarin.Interactive.Client/Compilation/CompilationWorkspaceFactory.cs index ffb8c4ebc..667316a78 100644 --- a/Clients/Xamarin.Interactive.Client/Compilation/CompilationWorkspaceFactory.cs +++ b/Clients/Xamarin.Interactive.Client/Compilation/CompilationWorkspaceFactory.cs @@ -17,6 +17,7 @@ using Xamarin.Interactive.Core; using Xamarin.Interactive.Logging; using Xamarin.Interactive.Reflection; +using Xamarin.Interactive.Representations.Reflection; using static Xamarin.Interactive.Compilation.InteractiveDependencyResolver; @@ -145,6 +146,8 @@ static InteractiveDependencyResolver CreateDependencyResolver ( static Assembly netStandardAssembly; static Assembly xiAssembly; + static Dictionary globalStateAssembliesByName = + new Dictionary (); static Type ResolveHostObjectType ( InteractiveDependencyResolver dependencyResolver, @@ -184,9 +187,16 @@ static Type ResolveHostObjectType ( Assembly globalStateAssembly; if (globalStateAssemblyDef.Name.Name == "Xamarin.Interactive") globalStateAssembly = xiAssembly; - else - globalStateAssembly = Assembly.ReflectionOnlyLoadFrom ( - globalStateAssemblyCachePath ?? globalStateAssemblyDef.Content.Location); + else { + // Cache assemblies in case subsequent agents lead us to try to load from a different location later. + // For example, if you create an XF workbook, we'll resolve from the remote assembly cache. If you + // then create a non-XF workbook, we'll resolve locally because PEImage doesn't get set for some reason. + if (!globalStateAssembliesByName.TryGetValue (configuration.GlobalStateAssembly.Name, out globalStateAssembly)) { + globalStateAssembly = Assembly.ReflectionOnlyLoadFrom ( + globalStateAssemblyCachePath ?? globalStateAssemblyDef.Content.Location); + globalStateAssembliesByName [configuration.GlobalStateAssembly.Name] = globalStateAssembly; + } + } return globalStateAssembly.GetType (configuration.GlobalStateTypeName); }