I was asked about this today (hi Sham!). It turns out to be very easy since the Windsor Container exposes it's dependency graph via it's GraphNodes collection. Here's a little console application that'll output the dependency graph of any application. You simply give it the path of the Windsor configuration file and the path of your application's bin folder.
Here's the output from a sample run:
C:\>Suteki.DependencyViewer "C:\source\Suteki\Suteki.SomeApplication\Configuration\Windsor.config" "C:\source\Suteki\Suteki.SomeApplication\bin" Suteki.SomeApplication.Controllers.StatusController Suteki.SomeApplication.Repositories.UserRepository Suteki.SomeApplication.SomeApplicationDataContext Suteki.SomeApplication.Repositories.InstructionRepository Suteki.SomeApplication.SomeApplicationDataContext Suteki.SomeApplication.Repositories.Repository`1 Suteki.SomeApplication.SomeApplicationDataContext Suteki.SomeApplication.Repositories.Repository`1 Suteki.SomeApplication.SomeApplicationDataContext Suteki.SomeApplication.Services.MatterSubmissionService Suteki.SomeApplication.MatterServiceProxy.MatterServiceClient Suteki.SomeApplication.Services.DocumentUploadServiceProxy Suteki.SomeApplication.Services.InstructionPdfService Suteki.SomeApplication.Service.Model.Services.DocumentService Suteki.SomeApplication.Service.Model.Services.DateService Suteki.SomeApplication.Services.EmailToFileSender Suteki.SomeApplication.Services.EmailTemplateService
And here's the code:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Castle.Windsor; using Castle.Core; using System.Reflection; using System.IO; namespace Suteki.DependencyViewer { public class Program { private Dictionary<string, Assembly> assemblyList; public static void Main(string[] args) { if (args.Length != 2) { Console.WriteLine("usage: Suteki.DependencyViewer <config file> <bin directory>"); return; } Program program = new Program(); program.Execute(args[0], args[1]); } private void Execute(string configPath, string binPath) { if (!File.Exists(configPath)) { Console.WriteLine("The config file at '{0}' does not exist"); } if (!Directory.Exists(binPath)) { Console.WriteLine("The bin directory at '{0}' does not exist"); } LoadDlls(binPath); WindsorContainer container = new WindsorContainer(configPath); GraphNode[] graphNodes = container.Kernel.GraphNodes; foreach (GraphNode graphNode in graphNodes) { if (graphNode.Dependers.Length == 0) { Console.WriteLine(); WalkGraph(graphNode, 0); } } } private void WalkGraph(IVertex node, int level) { ComponentModel componentModel = node as ComponentModel; if (componentModel != null) { Console.WriteLine("{0}{1}", new string('\t', level), componentModel.Implementation.FullName); } foreach (IVertex childNode in node.Adjacencies) { WalkGraph(childNode, level + 1); } } private void LoadDlls(string binPath) { AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); string[] dlls = System.IO.Directory.GetFiles(binPath, "*.dll"); assemblyList = new Dictionary<string, Assembly>(dlls.Length); foreach (String fileName in dlls) { Assembly asm = System.Reflection.Assembly.LoadFrom(fileName); assemblyList.Add(asm.FullName.Split(',')[0], asm); } } Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { return assemblyList[args.Name]; } } }
The title said something about graph, so where is the graph ?
ReplyDeleteAnonymous, very good ;)
ReplyDeleteThanks for thinking to post this.
ReplyDelete