Exemplo n.º 1
0
        private static List <AssemblyCandidate> LoadAllUserAssemblies2(UserQueryTypeInfo userQuery, QueryInfo currentQuery)
        {
            // strategy for finding what assembly version to bundle
            // whenever there is a version ambiguity, we will remove the version that CloudPad referenced
            // (multiple versions show up because users bring in different code not same)

            var currentDomain = AppDomain.CurrentDomain;

            var cs = new AssemblyCandidateSet();

            // the purpose of this code is to get the typed data context, if used

            cs.Add(userQuery.Assembly.Location, userQuery.Assembly.GetName(), "<UserQuery>");

            foreach (var r in userQuery.Assembly.GetReferencedAssemblies())
            {
                var b = currentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == r.FullName); // if exact
                if (b != null)
                {
                    cs.Add(b.Location, r, "<UserQuery>");
                }
                else
                {
                    var referencedAssembly = Assembly.Load(r.FullName);
                    if (referencedAssembly.FullName == r.FullName)
                    {
                        cs.Add(referencedAssembly.Location, r, "<UserQuery>");
                    }
                }
            }

            // the rest is solved for us by LINQPad

            foreach (var f in currentQuery.GetFileReferences())
            {
                var name = AssemblyName.GetAssemblyName(f);
                cs.Add(f, name, "<File>");
            }

            foreach (var nuget in currentQuery.GetNuGetReferences())
            {
                var packageID = nuget.PackageID;
                foreach (var f in nuget.GetAssemblyReferences())
                {
                    var name = AssemblyName.GetAssemblyName(f);
                    cs.Add(f, name, packageID);
                }
            }

            // ====

            void unrefReferencedAssemblies(Assembly assembly)
            {
                foreach (var r in assembly.GetReferencedAssemblies())
                {
                    Debug.WriteLine($"Unref '{r.FullName}'", nameof(Compiler));
                    if (cs.Unref(r))
                    {
                        var b = currentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == r.FullName); // if exact
                        if (b != null)
                        {
                            unrefReferencedAssemblies(b);
                        }
                        else
                        {
                            Debug.WriteLine($"UnrefLoad '{r}'", nameof(Compiler));
                            var referencedAssembly = Assembly.Load(r.FullName);
                            Debug.WriteLine($"UnrefLoaded '{referencedAssembly.FullName}'\n from location '{referencedAssembly.Location}'", nameof(Compiler));
                            if (referencedAssembly.FullName == r.FullName)
                            { // if exact
                                unrefReferencedAssemblies(referencedAssembly);
                            }
                        }
                    }
                }
            }

            var cp = typeof(Program).Assembly; // CloudPad assembly

            // Unref everything that CloudPad brings in
            // we don't need it and it will intermingle
            // with other versions which we don't want.

            if (cs.Unref(cp.GetName()))
            {
                unrefReferencedAssemblies(cp);
            }

            // ====

            var fs = new List <AssemblyCandidate>();

            // ====

            var excludeLocations = new List <string>()
            {
                // Ignore stuff from LINQPad installation dir
                CanonicalDirectoryName(Path.GetDirectoryName(Assembly.Load("LINQPad").Location)),

                // Ignore stuff from azure-functions-core-tools installation dir
                CanonicalDirectoryName(Env.GetProgramDataDirectory()), // only necessary when running from within LINQPad but it doesn't hurt

                // Ignore stuff from Windows installation dir
                CanonicalDirectoryName(Environment.GetEnvironmentVariable("WINDIR")),
            };

            bool shouldExcludeLocation(string location)
            {
                foreach (var excludeLocation in excludeLocations)
                {
                    if (location.StartsWith(excludeLocation, StringComparison.OrdinalIgnoreCase))
                    {
                        return(true);
                    }
                }
                return(false);
            }

            // ====

            foreach (var item in cs.Set)
            {
                if (AssemblyBindingTarget.Exclude(item.Key))
                {
                    // we don't want to pack files that ship as part of the Azure Functions host
                    continue;
                }
                var list = item.Value;
                var c    = list[list.Count - 1]; // use highest version
                if (1 < list.Count)
                {
                    Trace.WriteLine($"Warning: Multiple versions of assembly '{c.Name.Name}' found.");
                    Trace.WriteLine($"Warning: Assembly with highest version '{c.Name.FullName}' from location '{c.Location}' used.");
                    Trace.WriteLine("Warning: The following verion(s) will not be used:");
                    for (int i = 0; i < list.Count - 1; i++)
                    {
                        var d = list[i];
                        Trace.WriteLine($"Warning:   Assembly '{d.FullName}' from location '{d.Location}' ignored.");
                    }
                }
                if (shouldExcludeLocation(c.Location))
                {
                    continue;
                }
                fs.Add(c);
            }
            ;

            // ====

            return(fs);
        }