Manages runtime assembly resolution for managed code functions, loading assemblies from their respective FunctionAssemblyLoadContext.
Inheritance: IDisposable
        internal CSharpFunctionInvoker(ScriptHost host, FunctionMetadata functionMetadata,
            Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings,
            IFunctionEntryPointResolver functionEntryPointResolver, FunctionAssemblyLoader assemblyLoader)
            : base(host, functionMetadata)
        {
            _host = host;
            _functionEntryPointResolver = functionEntryPointResolver;
            _assemblyLoader = assemblyLoader;
            _metadataResolver = new FunctionMetadataResolver(functionMetadata, TraceWriter);
            _inputBindings = inputBindings;
            _outputBindings = outputBindings;
            _triggerInputName = GetTriggerInputName(functionMetadata);
            _metrics = host.ScriptConfig.HostConfig.GetService<IMetricsLogger>();

            InitializeFileWatcherIfEnabled();
            _resultProcessor = CreateResultProcessor();

            _functionValueLoader = FunctionValueLoader.Create(CreateFunctionTarget);

            _reloadScript = ReloadScript;
            _reloadScript = _reloadScript.Debounce();

            _restorePackages = RestorePackages;
            _restorePackages = _restorePackages.Debounce();
        }
Beispiel #2
0
 public DotNetFunctionDescriptorProvider(ScriptHost host, ScriptHostConfiguration config,
                                         ICompilationServiceFactory <ICompilationService <IDotNetCompilation>, IFunctionMetadataResolver> compilationServiceFactory)
     : base(host, config)
 {
     _assemblyLoader            = new FunctionAssemblyLoader(config.RootScriptPath);
     _compilationServiceFactory = compilationServiceFactory;
 }
        internal DotNetFunctionInvoker(ScriptHost host, FunctionMetadata functionMetadata,
                                       Collection <FunctionBinding> inputBindings, Collection <FunctionBinding> outputBindings,
                                       IFunctionEntryPointResolver functionEntryPointResolver, FunctionAssemblyLoader assemblyLoader,
                                       ICompilationServiceFactory compilationServiceFactory)
            : base(host, functionMetadata)
        {
            _functionEntryPointResolver = functionEntryPointResolver;
            _assemblyLoader             = assemblyLoader;
            _metadataResolver           = new FunctionMetadataResolver(functionMetadata, host.ScriptConfig.BindingProviders, TraceWriter);
            _compilationService         = compilationServiceFactory.CreateService(functionMetadata.ScriptType, _metadataResolver);
            _inputBindings    = inputBindings;
            _outputBindings   = outputBindings;
            _triggerInputName = functionMetadata.Bindings.FirstOrDefault(b => b.IsTrigger).Name;
            _metrics          = host.ScriptConfig.HostConfig.GetService <IMetricsLogger>();

            InitializeFileWatcher();

            _resultProcessor = CreateResultProcessor();

            _functionValueLoader = FunctionValueLoader.Create(CreateFunctionTarget);

            _reloadScript = ReloadScript;
            _reloadScript = _reloadScript.Debounce();

            _restorePackages = RestorePackages;
            _restorePackages = _restorePackages.Debounce();
        }
        internal DotNetFunctionInvoker(ScriptHost host, FunctionMetadata functionMetadata,
            Collection<FunctionBinding> inputBindings, Collection<FunctionBinding> outputBindings,
            IFunctionEntryPointResolver functionEntryPointResolver, FunctionAssemblyLoader assemblyLoader,
            ICompilationServiceFactory compilationServiceFactory, ITraceWriterFactory traceWriterFactory = null)
            : base(host, functionMetadata, traceWriterFactory)
        {
            _metricsLogger = Host.ScriptConfig.HostConfig.GetService<IMetricsLogger>();
            _functionEntryPointResolver = functionEntryPointResolver;
            _assemblyLoader = assemblyLoader;
            _metadataResolver = new FunctionMetadataResolver(functionMetadata, host.ScriptConfig.BindingProviders, TraceWriter);
            _compilationService = compilationServiceFactory.CreateService(functionMetadata.ScriptType, _metadataResolver);
            _inputBindings = inputBindings;
            _outputBindings = outputBindings;
            _triggerInputName = functionMetadata.Bindings.FirstOrDefault(b => b.IsTrigger).Name;

            InitializeFileWatcher();

            _resultProcessor = CreateResultProcessor();

            _functionLoader = new FunctionLoader<MethodInfo>(CreateFunctionTarget);

            _reloadScript = ReloadScript;
            _reloadScript = _reloadScript.Debounce();

            _restorePackages = RestorePackages;
            _restorePackages = _restorePackages.Debounce();
        }
Beispiel #5
0
        internal DotNetFunctionInvoker(ScriptHost host,
                                       FunctionMetadata functionMetadata,
                                       Collection <FunctionBinding> inputBindings,
                                       Collection <FunctionBinding> outputBindings,
                                       IFunctionEntryPointResolver functionEntryPointResolver,
                                       FunctionAssemblyLoader assemblyLoader,
                                       ICompilationServiceFactory <ICompilationService <IDotNetCompilation>, IFunctionMetadataResolver> compilationServiceFactory,
                                       IFunctionMetadataResolver metadataResolver = null)
            : base(host, functionMetadata)
        {
            _metricsLogger = Host.ScriptConfig.HostConfig.GetService <IMetricsLogger>();
            _functionEntryPointResolver = functionEntryPointResolver;
            _assemblyLoader             = assemblyLoader;
            _metadataResolver           = metadataResolver ?? CreateMetadataResolver(host, functionMetadata, TraceWriter);
            _compilationService         = compilationServiceFactory.CreateService(functionMetadata.ScriptType, _metadataResolver);
            _inputBindings    = inputBindings;
            _outputBindings   = outputBindings;
            _triggerInputName = functionMetadata.Bindings.FirstOrDefault(b => b.IsTrigger).Name;

            InitializeFileWatcher();

            _resultProcessor = CreateResultProcessor();

            _functionLoader = new FunctionLoader <MethodInfo>(CreateFunctionTarget);

            _reloadScript = ReloadScriptAsync;
            _reloadScript = _reloadScript.Debounce();

            _onReferencesChanged = OnReferencesChanged;
            _onReferencesChanged = _onReferencesChanged.Debounce();

            _restorePackages = RestorePackages;
            _restorePackages = _restorePackages.Debounce();
        }
        internal CSharpFunctionInvoker(ScriptHost host, FunctionMetadata functionMetadata,
                                       Collection <FunctionBinding> inputBindings, Collection <FunctionBinding> outputBindings,
                                       IFunctionEntryPointResolver functionEntryPointResolver, FunctionAssemblyLoader assemblyLoader)
            : base(host, functionMetadata)
        {
            _host = host;
            _functionEntryPointResolver = functionEntryPointResolver;
            _assemblyLoader             = assemblyLoader;
            _metadataResolver           = new FunctionMetadataResolver(functionMetadata, TraceWriter);
            _inputBindings    = inputBindings;
            _outputBindings   = outputBindings;
            _triggerInputName = GetTriggerInputName(functionMetadata);
            _metrics          = host.ScriptConfig.HostConfig.GetService <IMetricsLogger>();

            InitializeFileWatcherIfEnabled();
            _resultProcessor = CreateResultProcessor();

            _functionValueLoader = FunctionValueLoader.Create(CreateFunctionTarget);

            _reloadScript = ReloadScript;
            _reloadScript = _reloadScript.Debounce();

            _restorePackages = RestorePackages;
            _restorePackages = _restorePackages.Debounce();
        }
 public DotNetFunctionDescriptorProvider(ScriptHost host, ScriptHostConfiguration config,
     ICompilationServiceFactory compilationServiceFactory)
     : base(host, config)
 {
     _assemblyLoader = new FunctionAssemblyLoader(config.RootScriptPath);
     _compilationServiceFactory = compilationServiceFactory;
 }
 public DotNetFunctionDescriptionProvider(ScriptHost host, ScriptHostConfiguration config,
                                          ICompilationServiceFactory compilationServiceFactory)
     : base(host, config)
 {
     _assemblyLoader            = new FunctionAssemblyLoader(config.RootScriptPath);
     _compilationServiceFactory = compilationServiceFactory;
 }
        public override void OnError(Exception ex)
        {
            string error = Utility.FlattenException(ex, s =>
            {
                string baseAssemblyName = FunctionAssemblyLoader.GetAssemblyNameFromMetadata(Metadata, string.Empty);
                if (s != null && s.StartsWith(baseAssemblyName))
                {
                    return(Metadata.Name);
                }

                return(s);
            });

            TraceError(error);
        }
Beispiel #10
0
        private Compilation GetScriptCompilation(Script <object> script, FunctionMetadata functionMetadata)
        {
            Compilation compilation = script.GetCompilation();

            if (_optimizationLevel == OptimizationLevel.Debug)
            {
                SyntaxTree scriptTree = compilation.SyntaxTrees.FirstOrDefault(t => string.IsNullOrEmpty(t.FilePath));
                var        debugTree  = SyntaxFactory.SyntaxTree(scriptTree.GetRoot(),
                                                                 encoding: UTF8WithNoBOM,
                                                                 path: Path.GetFileName(functionMetadata.ScriptFile),
                                                                 options: new CSharpParseOptions(kind: SourceCodeKind.Script));

                compilation = compilation
                              .RemoveAllSyntaxTrees()
                              .AddSyntaxTrees(debugTree);
            }

            return(compilation.WithOptions(compilation.Options.WithOptimizationLevel(_optimizationLevel))
                   .WithAssemblyName(FunctionAssemblyLoader.GetAssemblyNameFromMetadata(functionMetadata, compilation.AssemblyName)));
        }
        public void ResolveAssembly_WithIndirectPrivateDependency_IsResolved()
        {
            var resolver = new FunctionAssemblyLoader("c:\\");

            var metadata1 = new FunctionMetadata { Name = "Test1", Source = @"c:\testroot\test1\test.tst" };
            var metadata2 = new FunctionMetadata { Name = "Test2", Source = @"c:\testroot\test2\test.tst" };
            var traceWriter = new TestTraceWriter(TraceLevel.Verbose);

            var mockResolver = new Mock<IFunctionMetadataResolver>();
            mockResolver.Setup(m => m.ResolveAssembly("MyTestAssembly.dll"))
              .Returns(new TestAssembly(new AssemblyName("MyTestAssembly")));
                
            resolver.CreateOrUpdateContext(metadata1, this.GetType().Assembly, new FunctionMetadataResolver(metadata1, traceWriter), traceWriter);
            resolver.CreateOrUpdateContext(metadata2, this.GetType().Assembly, mockResolver.Object, traceWriter);

            Assembly result = resolver.ResolveAssembly(null, new System.ResolveEventArgs("MyTestAssembly.dll",
                new TestAssembly(new AssemblyName("MyDirectReference"), @"file:///c:/testroot/test2/bin/MyDirectReference.dll")));

            Assert.NotNull(result);
        }
        public void ResolveAssembly_WithIndirectPrivateDependency_LogsIfResolutionFails()
        {
            var resolver = new FunctionAssemblyLoader("c:\\");

            var metadata1 = new FunctionMetadata { Name = "Test1", ScriptFile = @"c:\testroot\test1\test.tst" };
            var metadata2 = new FunctionMetadata { Name = "Test2", ScriptFile = @"c:\testroot\test2\test.tst" };
            var traceWriter = new TestTraceWriter(TraceLevel.Verbose);

            var mockResolver = new Mock<IFunctionMetadataResolver>();
            mockResolver.Setup(m => m.ResolveAssembly("MyTestAssembly.dll"))
              .Returns<Assembly>(null);

            resolver.CreateOrUpdateContext(metadata1, this.GetType().Assembly, new FunctionMetadataResolver(metadata1, new Collection<ScriptBindingProvider>(), traceWriter), traceWriter);
            resolver.CreateOrUpdateContext(metadata2, this.GetType().Assembly, mockResolver.Object, traceWriter);

            Assembly result = resolver.ResolveAssembly(AppDomain.CurrentDomain, new System.ResolveEventArgs("MyTestAssembly.dll",
                new TestAssembly(new AssemblyName("MyDirectReference"), @"file:///c:/testroot/test2/bin/MyDirectReference.dll")));

            Assert.Null(result);
            Assert.Equal(1, traceWriter.Traces.Count);
            Assert.Contains("MyTestAssembly.dll", traceWriter.Traces[0].Message);
        }
Beispiel #13
0
        public Task <IDotNetCompilation> GetFunctionCompilationAsync(FunctionMetadata functionMetadata)
        {
            // First use the C# compiler to resolve references, to get consistency with the C# Azure Functions programming model
            // Add the #r statements from the .fsx file to the resolver source
            string scriptSource          = GetFunctionSource(functionMetadata);
            var    resolverSourceBuilder = new StringBuilder();

            using (StringReader sr = new StringReader(scriptSource))
            {
                string line;

                while ((line = sr.ReadLine()) != null)
                {
                    if (_hashRRegex.IsMatch(line))
                    {
                        resolverSourceBuilder.AppendLine(line);
                    }
                }
            }

            resolverSourceBuilder.AppendLine("using System;");
            var resolverSource = resolverSourceBuilder.ToString();

            Script <object> script = CodeAnalysis.CSharp.Scripting.CSharpScript.Create(resolverSource, options: _metadataResolver.CreateScriptOptions(), assemblyLoader: AssemblyLoader.Value);

            var compiler = new SimpleSourceCodeServices(msbuildEnabled: FSharpOption <bool> .Some(false));

            FSharpErrorInfo[]       errors         = null;
            FSharpOption <Assembly> assemblyOption = null;

            string scriptPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

            Directory.CreateDirectory(scriptPath);

            string scriptFilePath = Path.Combine(scriptPath, Path.GetFileName(functionMetadata.ScriptFile));

            var assemblyName     = FunctionAssemblyLoader.GetAssemblyNameFromMetadata(functionMetadata, Guid.NewGuid().ToString());
            var assemblyFileName = Path.Combine(scriptPath, assemblyName + ".dll");
            var pdbName          = Path.ChangeExtension(assemblyFileName, PlatformHelper.IsMono ? "dll.mdb" : "pdb");

            try
            {
                var scriptFileBuilder = new StringBuilder();

                // Write an adjusted version of the script file, prefixing some 'open' declarations
                foreach (string import in script.Options.Imports)
                {
                    scriptFileBuilder.AppendLine("open " + import);
                }

                // Suppress undesirable warnings
                scriptFileBuilder.AppendLine("#nowarn \"988\"");

                // Set the line to match the original script
                scriptFileBuilder.AppendLine("# 0 @\"" + functionMetadata.ScriptFile + "\"");

                // Add our original script
                scriptFileBuilder.AppendLine(scriptSource);

                File.WriteAllText(scriptFilePath, scriptFileBuilder.ToString());

                var otherFlags = new List <string>();

                otherFlags.Add("fsc.exe");

                // The --noframework option is used because we will shortly add references to mscorlib and FSharp.Core
                // as dictated by the C# reference resolver, and F# doesn't like getting multiple references to those.
                otherFlags.Add("--noframework");

                var references = script.GetCompilation().References
                                 .Where(m => !(m is UnresolvedMetadataReference))
                                 .Select(m => "-r:" + m.Display)
                                 .Distinct(new FileNameEqualityComparer());

                // Add the references as reported by the metadata resolver.
                otherFlags.AddRange(references);

                if (_optimizationLevel == OptimizationLevel.Debug)
                {
                    otherFlags.Add("--optimize-");
                    otherFlags.Add("--debug+");
                    otherFlags.Add("--tailcalls-");
                }

                if (PlatformHelper.IsMono)
                {
                    var monoDir    = Path.GetDirectoryName(typeof(string).Assembly.Location);
                    var facadesDir = Path.Combine(monoDir, "Facades");
                    otherFlags.Add("--lib:" + facadesDir);
                }

                // If we have a private assembly folder, make sure the compiler uses it to resolve dependencies
                string privateAssembliesFolder = Path.Combine(Path.GetDirectoryName(functionMetadata.ScriptFile), DotNetConstants.PrivateAssembliesFolderName);
                if (Directory.Exists(privateAssembliesFolder))
                {
                    otherFlags.Add("--lib:" + Path.Combine(Path.GetDirectoryName(functionMetadata.ScriptFile), DotNetConstants.PrivateAssembliesFolderName));
                }

                otherFlags.Add("--out:" + assemblyFileName);

                // Get the #load closure
                FSharpChecker checker = FSharpChecker.Create(null, null, null, msbuildEnabled: FSharpOption <bool> .Some(false));
                var           loadFileOptionsAsync = checker.GetProjectOptionsFromScript(functionMetadata.ScriptFile, scriptSource, null, null, null);
                var           loadFileOptions      = FSharp.Control.FSharpAsync.RunSynchronously(loadFileOptionsAsync, null, null);
                foreach (var loadedFileName in loadFileOptions.ProjectFileNames)
                {
                    if (Path.GetFileName(loadedFileName) != Path.GetFileName(functionMetadata.ScriptFile))
                    {
                        otherFlags.Add(loadedFileName);
                    }
                }

                // Add the (adjusted) script file itself
                otherFlags.Add(scriptFilePath);

                // Compile the script to a static assembly
                var result = compiler.Compile(otherFlags.ToArray());
                errors = result.Item1;
                var code = result.Item2;

                if (code == 0)
                {
                    var    assemblyBytes = File.ReadAllBytes(assemblyFileName);
                    byte[] pdbBytes      = null;
                    if (File.Exists(pdbName))
                    {
                        pdbBytes = File.ReadAllBytes(pdbName);
                    }
                    var assembly = Assembly.Load(assemblyBytes, pdbBytes);
                    assemblyOption = FSharpOption <Assembly> .Some(assembly);
                }
                else
                {
                    string message = $"F# compilation failed with arguments: {string.Join(" ", otherFlags)}";
                    _traceWriter.Verbose(message);
                    _logger?.LogDebug(message);
                }
            }
            finally
            {
                DeleteDirectoryAsync(scriptPath, recursive: true)
                .ContinueWith(
                    t => t.Exception.Handle(e =>
                {
                    string message = $"Unable to delete F# compilation file: {e.ToString()}";
                    _traceWriter.Warning(message);
                    _logger?.LogWarning(message);
                    return(true);
                }), TaskContinuationOptions.OnlyOnFaulted);
            }

            return(Task.FromResult <IDotNetCompilation>(new FSharpCompilation(errors, assemblyOption)));
        }
 public CSharpFunctionDescriptionProvider(ScriptHost host, ScriptHostConfiguration config)
     : base(host, config)
 {
     _assemblyLoader = new FunctionAssemblyLoader(config.RootScriptPath);
 }
 public CSharpFunctionDescriptionProvider(ScriptHost host, ScriptHostConfiguration config)
     : base(host, config)
 {
     _assemblyLoader = new FunctionAssemblyLoader(config.RootScriptPath);
 }
Beispiel #16
0
        public ICompilation GetFunctionCompilation(FunctionMetadata functionMetadata)
        {
            // First use the C# compiler to resolve references, to get consistency with the C# Azure Functions programming model
            // Add the #r statements from the .fsx file to the resolver source
            string scriptSource          = GetFunctionSource(functionMetadata);
            var    resolverSourceBuilder = new StringBuilder();

            using (StringReader sr = new StringReader(scriptSource))
            {
                string line;

                while ((line = sr.ReadLine()) != null)
                {
                    if (_hashRRegex.IsMatch(line))
                    {
                        resolverSourceBuilder.AppendLine(line);
                    }
                }
            }

            resolverSourceBuilder.AppendLine("using System;");
            var resolverSource = resolverSourceBuilder.ToString();

            Script <object> script      = CodeAnalysis.CSharp.Scripting.CSharpScript.Create(resolverSource, options: _metadataResolver.CreateScriptOptions(), assemblyLoader: AssemblyLoader.Value);
            Compilation     compilation = script.GetCompilation();

            var compiler = new SimpleSourceCodeServices(msbuildEnabled: FSharpOption <bool> .Some(false));

            FSharpErrorInfo[]       errors         = null;
            FSharpOption <Assembly> assemblyOption = null;
            string scriptFilePath = Path.Combine(Path.GetTempPath(), Path.GetFileName(functionMetadata.ScriptFile));

            var asmName = FunctionAssemblyLoader.GetAssemblyNameFromMetadata(functionMetadata, compilation.AssemblyName);
            var dllName = Path.GetTempPath() + asmName + ".dll";
            var pdbName = Path.ChangeExtension(dllName, "pdb");

            try
            {
                var scriptFileBuilder = new StringBuilder();

                // Write an adjusted version of the script file, prefixing some 'open' decarations
                foreach (string import in script.Options.Imports)
                {
                    scriptFileBuilder.AppendLine("open " + import);
                }

                // Suppress undesirable warnings
                scriptFileBuilder.AppendLine("#nowarn \"988\"");

                // Set the line to match the original script
                scriptFileBuilder.AppendLine("# 0 @\"" + functionMetadata.ScriptFile + "\"");

                // Add our original script
                scriptFileBuilder.AppendLine(scriptSource);

                File.WriteAllText(scriptFilePath, scriptFileBuilder.ToString());

                var otherFlags = new List <string>();

                // For some reason CompileToDynamicAssembly wants "fsc.exe" as the first arg, it is ignored.
                otherFlags.Add("fsc.exe");

                // The --noframework option is used because we will shortly add references to mscorlib and FSharp.Core
                // as dictated by the C# reference resolver, and F# doesn't like getting multiple references to those.
                otherFlags.Add("--noframework");

                // Add the references as reported by the C# reference resolver.
                foreach (var mdr in compilation.References)
                {
                    if (!mdr.Display.Contains("Unresolved "))
                    {
                        otherFlags.Add("-r:" + mdr.Display);
                    }
                }

                // Above we have used the C# reference resolver to get the basic set of DLL references for the compilation.
                //
                // However F# has its own view on default options. For scripts these should include the
                // following framework facade references.

                otherFlags.Add("-r:System.Linq.dll");             // System.Linq.Expressions.Expression<T>
                otherFlags.Add("-r:System.Reflection.dll");       // System.Reflection.ParameterInfo
                otherFlags.Add("-r:System.Linq.Expressions.dll"); // System.Linq.IQueryable<T>
                otherFlags.Add("-r:System.Threading.Tasks.dll");  // valuetype [System.Threading.Tasks]System.Threading.CancellationToken
                otherFlags.Add("-r:System.IO.dll");               //  System.IO.TextWriter
                otherFlags.Add("-r:System.Net.Requests.dll");     //  System.Net.WebResponse etc.
                otherFlags.Add("-r:System.Collections.dll");      // System.Collections.Generic.List<T>
                otherFlags.Add("-r:System.Runtime.Numerics.dll"); // BigInteger
                otherFlags.Add("-r:System.Threading.dll");        // OperationCanceledException
                otherFlags.Add("-r:System.Runtime.dll");
                otherFlags.Add("-r:System.Numerics.dll");

                if (_optimizationLevel == OptimizationLevel.Debug)
                {
                    otherFlags.Add("--optimize-");
                    otherFlags.Add("--debug+");
                    otherFlags.Add("--tailcalls-");
                }

                // If we have a private assembly folder, make sure the compiler uses it to resolve dependencies
                string privateAssembliesFolder = Path.Combine(Path.GetDirectoryName(functionMetadata.ScriptFile), DotNetConstants.PrivateAssembliesFolderName);
                if (Directory.Exists(privateAssembliesFolder))
                {
                    otherFlags.Add("--lib:" + Path.Combine(Path.GetDirectoryName(functionMetadata.ScriptFile), DotNetConstants.PrivateAssembliesFolderName));
                }

                otherFlags.Add("--out:" + dllName);

                // Get the #load closure
                FSharpChecker checker = FSharpChecker.Create(null, null, null, msbuildEnabled: FSharpOption <bool> .Some(false));
                var           loadFileOptionsAsync = checker.GetProjectOptionsFromScript(functionMetadata.ScriptFile, scriptSource, null, null, null);
                var           loadFileOptions      = FSharp.Control.FSharpAsync.RunSynchronously(loadFileOptionsAsync, null, null);
                foreach (var loadedFileName in loadFileOptions.ProjectFileNames)
                {
                    if (Path.GetFileName(loadedFileName) != Path.GetFileName(functionMetadata.ScriptFile))
                    {
                        otherFlags.Add(loadedFileName);
                    }
                }

                // Add the (adjusted) script file itself
                otherFlags.Add(scriptFilePath);

                // Compile the script to a static assembly
                var result = compiler.Compile(otherFlags.ToArray());
                errors = result.Item1;
                var code = result.Item2;

                if (code == 0)
                {
                    var    assemblyBytes = File.ReadAllBytes(dllName);
                    byte[] pdbBytes      = null;
                    if (File.Exists(pdbName))
                    {
                        pdbBytes = File.ReadAllBytes(pdbName);
                    }
                    var assembly = Assembly.Load(assemblyBytes, pdbBytes);
                    assemblyOption = FSharpOption <Assembly> .Some(assembly);
                }
            }
            finally
            {
                Task.WhenAll(DeleteIfExistsAsync(scriptFilePath), DeleteIfExistsAsync(dllName), DeleteIfExistsAsync(pdbName))
                .ContinueWith(t => t.Exception.Handle(e =>
                {
                    // TODO: Trace
                    return(true);
                }), TaskContinuationOptions.OnlyOnFaulted);
            }

            return(new FSharpCompilation(errors, assemblyOption));
        }