Example #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AppDomainIntellisenseSession"/> class.
        /// </summary>
        /// <param name="assembliesToLoad">
        /// The assemblies.
        /// </param>
        /// <param name="fallbackConnectQl">
        /// The fallback ConnectQl assembly when no reference is available in the project.
        /// </param>
        public AppDomainIntellisenseSession(IList <string> assembliesToLoad, string fallbackConnectQl)
        {
            var sw = Stopwatch.StartNew();

            var referencedAssemblies = new List <Assembly>();
            var loadedAssemblies     = new List <LoadedAssembly> {
                new LoadedAssembly(this.GetType().Assembly)
            };

            AppDomain.CurrentDomain.AssemblyResolve += AppDomainIntellisenseSession.CreateAssemblyResolver(loadedAssemblies);

            AppDomainIntellisenseSession.LoadAssemblies(
                assembliesToLoad.Where(AppDomainIntellisenseSession.IsIntellisenseAssembly),
                referencedAssemblies,
                loadedAssemblies);

            var connectQl = AppDomainIntellisenseSession.GetConnectQlAssembly(fallbackConnectQl, loadedAssemblies, referencedAssemblies);

            var assemblyLookup = loadedAssemblies.ToDictionary(a => a.Assembly.GetName().ToString());

            var pluginLoaderType     = connectQl.GetType("ConnectQl.Intellisense.AssemblyPluginResolver");
            var pluginLoader         = Activator.CreateInstance(pluginLoaderType, referencedAssemblies);
            var contextType          = connectQl.GetType("ConnectQl.ConnectQlContext");
            var contextInterfaceType = connectQl.GetType("ConnectQl.Intellisense.IConnectQlContext");
            var createSession        = connectQl.GetType("ConnectQl.Intellisense.ConnectQlExtensions").GetMethod("CreateIntellisenseSession");
            var sessionType          = connectQl.GetType("ConnectQl.Intellisense.IntellisenseSession");

            this.context = Activator.CreateInstance(contextType, pluginLoader);
            this.session = createSession.Invoke(null, new[] { this.context });

            this.executeToByteArrayAsync = contextInterfaceType?.GetMethod("ExecuteToByteArrayAsync");
            this.getDocument             = sessionType.GetMethod("GetDocumentAsByteArray");
            this.removeDocument          = sessionType.GetMethod("RemoveDocument");
            this.updateDocument          = sessionType.GetMethod("UpdateDocument");
            this.updateDocumentSpan      = sessionType.GetMethod("UpdateDocumentSpan");

            sessionType.GetEvent("InternalDocumentUpdated", BindingFlags.Public | BindingFlags.Instance)
            ?.AddEventHandler(this.session, Delegate.CreateDelegate(typeof(EventHandler <byte[]>), this, nameof(this.HandleEvent)));

            Debug.WriteLine($"Intellisense load took {sw.ElapsedMilliseconds}ms.");

            AppDomainIntellisenseSession.LoadAssemblies(
                assembliesToLoad.Where(a => !AppDomainIntellisenseSession.IsIntellisenseAssembly(a)),
                referencedAssemblies,
                loadedAssemblies);

            AppDomainIntellisenseSession.LoadReferencesRecursively(loadedAssemblies, assemblyLookup);

            pluginLoaderType.GetProperty("IsLoading")?.SetValue(pluginLoader, false);
            pluginLoaderType.GetMethod("AddAssemblies")?.Invoke(pluginLoader, new object[] { referencedAssemblies });

            Debug.WriteLine($"Appdomain load took {sw.ElapsedMilliseconds}ms.");
        }
Example #2
0
        /// <summary>
        /// Loads the assembly references recursively.
        /// </summary>
        /// <param name="assemblies">
        /// The assemblies.
        /// </param>
        /// <param name="assemblyLookup">
        /// The assembly lookup.
        /// </param>
        private static void LoadReferencesRecursively(List <LoadedAssembly> assemblies, IDictionary <string, LoadedAssembly> assemblyLookup)
        {
            var extraAssemblies = new List <LoadedAssembly>();

            foreach (var loadedAssembly in assemblies.ToArray())
            {
                try
                {
                    foreach (var reference in loadedAssembly.Assembly.GetReferencedAssemblies())
                    {
                        if (assemblyLookup.Any(a => a.Key.Split(',')[0].Equals(reference.ToString().Split(',')[0], StringComparison.OrdinalIgnoreCase)))
                        {
                            continue;
                        }

                        try
                        {
                            var dlls = new[]
                            {
                                $"{reference.Name}.dll",
                                Path.Combine(Path.GetDirectoryName(loadedAssembly.Path) ?? string.Empty, $"{reference.Name}.dll")
                            };

                            var dll = dlls.FirstOrDefault(File.Exists);

                            if (dll != null)
                            {
                                var pdb      = Regex.Replace(dll, @"\.dll$", ".pdb", RegexOptions.IgnoreCase);
                                var assembly = Assembly.Load(File.ReadAllBytes(dll), File.Exists(pdb) ? File.ReadAllBytes(pdb) : null, SecurityContextSource.CurrentAppDomain);
                                var loaded   = new LoadedAssembly(assembly, dll);

                                extraAssemblies.Add(loaded);
                                assemblyLookup[assembly.GetName().ToString()] = loaded;
                            }
                        }
                        catch (FileNotFoundException)
                        {
                        }
                    }
                }
                catch
                {
                    //// Do nothing.
                }
            }

            if (extraAssemblies.Count > 0)
            {
                AppDomainIntellisenseSession.LoadReferencesRecursively(extraAssemblies, assemblyLookup);

                assemblies.AddRange(extraAssemblies);
            }
        }