/// <summary>This is a helper method for the caller's benefit.  It flattens the tree.
 /// http://stackoverflow.com/questions/1938409/linq-how-to-convert-the-nested-hierarchical-object-to-flatten-object
 /// </summary>
 /// <param name="parent"></param>
 /// <returns></returns>
 private static IEnumerable<AssemblynameNode> Flatten(AssemblynameNode parent)
 {
     yield return parent;
     foreach (AssemblynameNode child in
         parent.ReferencedAssemblyNames ?? new List<AssemblynameNode>()
         )
     {
         foreach (AssemblynameNode relative in Flatten(child))
         {
             yield return relative;
         }
     }
 }
            /// <summary>This is a helper method for the caller's benefit.  It flattens the tree.
            /// http://stackoverflow.com/questions/1938409/linq-how-to-convert-the-nested-hierarchical-object-to-flatten-object
            /// </summary>
            /// <param name="parent"></param>
            /// <returns></returns>
            private static IEnumerable <AssemblynameNode> Flatten(AssemblynameNode parent)
            {
                yield return(parent);

                foreach (AssemblynameNode child in
                         parent.ReferencedAssemblyNames ?? new List <AssemblynameNode>()
                         )
                {
                    foreach (AssemblynameNode relative in Flatten(child))
                    {
                        yield return(relative);
                    }
                }
            }
예제 #3
0
        /// <summary>This is the method for recursing through the AssemblyNames.
        /// It returns a tree of AssemblyNames.
        /// </summary>
        /// <param name="assembly"></param>
        /// <returns></returns>
        private static AssemblynameNode GetRecursive(Assembly assembly)
        {
            if (null == assembly)
            {
                throw new System.ArgumentNullException("assembly");
            }

            //  http://msdn.microsoft.com/en-us/magazine/cc163641.aspx <- reflection
            //  http://dotnetdebug.net/2005/11/15/net-assembly-loader/
            //  http://stackoverflow.com/questions/3971793/what-when-assembly-getreferencedassemblies-returns-exe-dependency    <- reflectiononlyload and ditto loadfrom.  solves which problem?

            //  We always have an AssemblyName to return.
            var ret = new AssemblynameNode(assembly.GetName());

            //  Loop through the AssemblyNames the actual Assembly references.  Note that we might have already been into the AssemblyName through
            //  another Assembly and then we have a circular reference which means stack overflow.  It is taken care of in the loop.
            foreach (var assemblyname in assembly.GetReferencedAssemblies())
            {
                //  We only want to set the Info to have a list if we are sure we have referenced assemblies.  If we don't have any referenced assemblies we will keep it as null.
                //  If we are in the loop we know there are references Assemblies.  Below is shorthand for making sure we have a List and not touch it if we already have a List.
                ret.ReferencedAssemblyNames = ret.ReferencedAssemblyNames ?? new List <AssemblynameNode>();

                //  Check if we alreay have found this Assemblyname.  If we have; add it as a node but don't recurse its siblings.
                if (_assemblynameList.ContainsKey(assemblyname.FullName))
                {
                    ret.ReferencedAssemblyNames.Add(new AssemblynameNode(assemblyname));
                }
                else
                {   //  The AssemblyName is new for us.
                    //  Add the AssemblyName to the list of AssemblyNames we have found.
                    _assemblynameList.Add(assemblyname.FullName, assemblyname);

                    //  Gotta load the Assembly to get its references.  Just AssemblyName won't do since AssemblyName doesn't have information about referenced Assemblies.
                    {
                        var ass = Assembly.Load(assemblyname.FullName);
                        ret.ReferencedAssemblyNames.Add(GetRecursive(ass));

// ReSharper disable RedundantAssignment
                        ass = null; //  How do I unload?  Can I?  Should I?
// ReSharper restore RedundantAssignment
                        //  Well... we can't unload in the default app domain.  We should create a new, temporary, app domain and load/unload it there.
                        //  Not being able to unload means we have a memory leak for every call.
                        //  http://blogs.msdn.com/b/jasonz/archive/2004/05/31/145105.aspx
                    }
                }
            }

            return(ret);
        }
예제 #4
0
        /// <summary>This is the method for recursing through the AssemblyNames.
        /// It returns a tree of AssemblyNames.
        /// </summary>
        /// <param name="assembly"></param>
        /// <returns></returns>
        private static AssemblynameNode GetRecursive(Assembly assembly)
        {
            if (null == assembly) { throw new System.ArgumentNullException("assembly"); }

            //  http://msdn.microsoft.com/en-us/magazine/cc163641.aspx <- reflection
            //  http://dotnetdebug.net/2005/11/15/net-assembly-loader/
            //  http://stackoverflow.com/questions/3971793/what-when-assembly-getreferencedassemblies-returns-exe-dependency    <- reflectiononlyload and ditto loadfrom.  solves which problem?

            //  We always have an AssemblyName to return.
            var ret = new AssemblynameNode(assembly.GetName());

            //  Loop through the AssemblyNames the actual Assembly references.  Note that we might have already been into the AssemblyName through
            //  another Assembly and then we have a circular reference which means stack overflow.  It is taken care of in the loop.
            foreach (var assemblyname in assembly.GetReferencedAssemblies())
            {
                //  We only want to set the Info to have a list if we are sure we have referenced assemblies.  If we don't have any referenced assemblies we will keep it as null.
                //  If we are in the loop we know there are references Assemblies.  Below is shorthand for making sure we have a List and not touch it if we already have a List.
                ret.ReferencedAssemblyNames = ret.ReferencedAssemblyNames ?? new List<AssemblynameNode>();

                //  Check if we alreay have found this Assemblyname.  If we have; add it as a node but don't recurse its siblings.
                if (_assemblynameList.ContainsKey(assemblyname.FullName))
                {
                    ret.ReferencedAssemblyNames.Add(new AssemblynameNode(assemblyname));
                }
                else
                {   //  The AssemblyName is new for us.

                    //  Add the AssemblyName to the list of AssemblyNames we have found.
                    _assemblynameList.Add(assemblyname.FullName, assemblyname);

                    //  Gotta load the Assembly to get its references.  Just AssemblyName won't do since AssemblyName doesn't have information about referenced Assemblies.
                    {
                        var ass = Assembly.Load(assemblyname.FullName);
                        ret.ReferencedAssemblyNames.Add(GetRecursive(ass));

            // ReSharper disable RedundantAssignment
                        ass = null; //  How do I unload?  Can I?  Should I?
            // ReSharper restore RedundantAssignment
                        //  Well... we can't unload in the default app domain.  We should create a new, temporary, app domain and load/unload it there.
                        //  Not being able to unload means we have a memory leak for every call.
                        //  http://blogs.msdn.com/b/jasonz/archive/2004/05/31/145105.aspx
                    }
                }
            }

            return ret;
        }