示例#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.");
        }
示例#2
0
        /// <summary>
        /// Gets the ConnectQl assembly.
        /// </summary>
        /// <param name="fallbackConnectQl">
        /// The assembly to fall back on, when it cannot be found in the project.
        /// </param>
        /// <param name="loadedAssemblies">
        /// The assemblies that were loaded.
        /// </param>
        /// <param name="referencedAssemblies">
        /// The assemblies that were referenced.
        /// </param>
        /// <returns>
        /// The ConnectQl assembly.
        /// </returns>
        private static Assembly GetConnectQlAssembly(string fallbackConnectQl, List <LoadedAssembly> loadedAssemblies, List <Assembly> referencedAssemblies)
        {
            var connectQl = AppDomainIntellisenseSession.GetConnectQlAssembly(loadedAssemblies, "ConnectQl");

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

                connectQl = AppDomainIntellisenseSession.GetConnectQlAssembly(loadedAssemblies, "ConnectQl");
            }

            return(connectQl);
        }