Thanks for the reply Harald and Dinis. Mono.Cecil is definately a huge step up from reflector. Thanks Jb Evian.
Both dotnetarchitect and the O2 project tool are good, and both have provided useful insights into what I need to do. However I am not sure if I can use either as a whole, as I need to generate a specific output that is read by the gql4jung project (code.google.com/p/ gql4jung), which performs a much more complicated analysis, including searching for architectural antipatterns and code smells in systems. Currently it only works with Java jars, but it will be able to work with .NET assemblies once they have been converted into the desired format. There are definately some interesting corner cases with the .NET assemblies. I am still working through how to deal with some of them. Thanks for the help and examples. Cheers, Andrew On Jan 19, 2:33 am, Dinis Cruz <[email protected]> wrote: > Hi Andrew, I think I implemented all you need (using Mono Cecil) at the OWASP > O2 Platform <http://www.owasp.org/index.php/OWASP_O2_Platform> > > <http://www.owasp.org/index.php/OWASP_O2_Platform>If you look at the Cir > Viewer module (ClickOnce > install<http://deploy.o2-ounceopen.com/O2_Tool_CirViewer/>, > source > code<http://code.google.com/p/o2platform/source/browse/trunk/O2%20-%20All%...>) > you will see that once you drop a .Net assembly in there you will have > access to all that information (i.e. what types are used by an assembly, > type of method). > > There are quite a number of locations where O2 uses MonoCecil (most of the > pluming code is in the > O2_External_MonoCecil<http://code.google.com/p/o2platform/source/browse/trunk/O2%20-%20All%...>module) > so you might want to give a good look, since I probably already have > a solution (or hack :) ) for your problem. > > For example, one of the key pieces of information I get from MonoCecil is > the list of methods that are called from inside a method (which is a great > way to know exactly what are a method/type/assembly dependency) > > So if you look at > CecilUtils.cs<http://code.google.com/p/o2platform/source/browse/trunk/O2%20-%20All%...> > you > will find the following example (Question to MonoCecil guys, is this the > right way to do this?) > > public static List<MethodCalled> > getMethodsCalledInsideAssembly(StringassemblyToLoad > ) > { > try > { > var methodsCalled = new List<MethodCalled>(); > foreach (MethodDefinition methodDefinition in getMethods( > assemblyToLoad)) > methodsCalled.AddRange(getMethodsCalledInsideMethod( > methodDefinition)); > return methodsCalled; > } > catch (Exception ex) > { > DI.log.ex(ex, "in CecilUtils.getMethodsCalledInsideAssembly" > ); > return null; > } > } > > public static List<MethodCalled> getMethodsCalledInsideMethod( > MethodDefinition methodDefinition) > { > try > { > var methodsCalled = new List<MethodCalled>(); > if (methodDefinition.Body != null) > { > SequencePoint currentSequencePoint = null; > foreach (Instruction instruction in methodDefinition. > Body.Instructions) > { > currentSequencePoint = > instruction.SequencePoint ??currentSequencePoint > ; > if (instruction.Operand != null) > { > switch (instruction.Operand.GetType().Name) > { > case "MethodReference": > case "MethodDefinition": > methodsCalled.Add(new MethodCalled(( > IMemberReference)instruction.Operand, currentSequencePoint)); > break; > default: > break; > } > } > } > } > return methodsCalled; > } > catch (Exception ex) > { > DI.log.ex(ex, "in CecilUtils.getMethodsCalledInsideMethod"); > return null; > } > } > > On another case, I think I had the exact problem that you seem to have, when > I wanted to move a dll and all its dependencies into a separate folder (this > is used by the O2 XRules and CSharpScripts when you start a debugging > session for a particular method). You can see my solution on the > CecilAssemblyDependencies.cs<http://code.google.com/p/o2platform/source/browse/trunk/O2%20-%20All%...> > which > has the following helper static methods: > > - Get dependencies lists using Recursive search > - public static List<string> getListOfDependenciesForType(Type type) > - public static List<string> > getListOfDependenciesForTypes(List<Type>types > ) > - public static List<string> > getListOfDependenciesForAssembly(stringassembly > ) > - public static List<string> getListOfDependenciesForAssemblies(List< > String> assemblies) > - public static List<string> getListOfDependenciesForAssemblies(List< > String> assemblies, List<String> directoriesWithSourceAssemblies) > - Get dependencies lists using NonRecursive search > - public static > Dictionary<string,string>getDictionaryOfDependenciesForAssembly_WithNoRecursiveSearch > (string assembly) > - Populate (i.e. copy) directory with References > - public static string populateDirectoryWithAllDependenciesOfAssembly( > string assemblyToAnalyze) > - public static string populateDirectoryWithAllDependenciesOfAssembly( > string assemblyToAnalyze, string loadDllsFrom) > - public static void populateDirectoryWithAllDependenciesOfAssembly( > string targetDirectory, string assemblyToAnalyze, > List<string>pathsToFindReferencedDlls > ) > > As you will see in the code, there are a number of conner cases that one > needs to handle (depending of how complex your assembly is). This code still > has a number of O2 dependencies, but if you want I'm happy to work with you > in making it more usable in a standalone way. > > I have to give a big Kudos (and thanks) to the MonoCecil guys since I had > tried to do this before with .NET reflector and it was a massive exercise in > frustration :) > > Dinis Cruz > > 2010/1/18 Andrew <[email protected]> > > > Hi, > > For each type in an assembly, I want to get a list of all the types > > that the given type is dependent on, i.e. those that are used as > > fields, properties, in methods, and anywhere else the type could use > > them. I want to include any types that happen to be defined in the > > same assembly. > > > Basically, the idea is to load an assembly, and for each type defined > > in the assembly, list all the type dependencies. > > > So far I have been able to get a list of used types from the assembly, > > and some dependencies, with > > > FileInfo f = new FileInfo("SomeAssembly.dll"); > > AssemblyDefinition assemDef = AssemblyFactory.GetAssembly > > (f.FullName); > > > foreach(ModuleDefinition mDef in assemDef.Modules){ > > foreach (TypeDefinition type in mDef.Types) { > > if(!"<Module>".Equals(type.FullName)){ > > Console.WriteLine (type.Name+" > > ["+type.Namespace+"]"); > > > foreach(MethodDefinition method in type.Methods) > > { > > if(method.HasBody){ > > foreach(Instruction instr in > > method.Body.Instructions){ > > if(instr.OpCode.OperandType > > == OperandType.InlineType){ > > Console.WriteLine > > ("\tUses type "+instr.Operand); > > } > > } > > } > > } > > } > > } > > } > > > but this doesn't work very well, as it doesn't list types defined in > > the assembly. It also misses a lot of types used in the code. > > > The plan is to have this dependency generator the basis of a > > dependency analyser. Are there any tools that can do this and the > > source code is available? I know of some such as reflector and > > NDepend, but I cannot see how they generate the list, as they do not > > seem to be open source. > > > I will have a look at Gendarme next, and see if that can help, but it > > seems focused in a different area. > > > Is there any way of getting this information using Cecil, or an other > > libraries, or am I going to have to go through the IL line by line > > looking for opcodes? > > > -- > > -- > > mono-cecil > >
-- -- mono-cecil
