# Friday, 16 March 2012
« Lesser Known CLR Custom Attributes -- Un... | Main | New Development Snapshot »
IKVM.Reflection: Inspecting an Assembly Without Loading Dependencies

One of the advantages of IKVM.Reflection over System.Reflection is that it is much easier to load an assembly without having to load its dependencies. This functionality is used by Mono's C# compiler to load referenced assemblies without having to (potentially) load the transitive closure of dependencies of those assemblies.

Here's a simple example that loads an assembly and prints its types and members:

using System;
using IKVM.Reflection;

class Program {
  const BindingFlags AllDeclared =
    BindingFlags.Public |
    BindingFlags.NonPublic |
    BindingFlags.Instance |
    BindingFlags.Static |
    BindingFlags.DeclaredOnly;

  static void Main(string[] args) {
    var universe = new Universe();
    universe.AssemblyResolve += AssemblyResolve;
    var assembly = universe.LoadFile(args[0]);
    foreach (var type in assembly.GetTypes()) {
      Console.WriteLine(type.FullName);
      WriteMembers(type.GetFields(AllDeclared));
      WriteMembers(type.GetProperties(AllDeclared));
      WriteMembers(type.GetEvents(AllDeclared));
      WriteMembers(type.GetConstructors(AllDeclared));
      WriteMembers(type.GetMethods(AllDeclared));
    }
  }

  static void WriteMembers(MemberInfo[] members) {
    foreach (var member in members)
      Console.WriteLine(" {0}", member);
  }

  static Assembly AssemblyResolve(object sender, IKVM.Reflection.ResolveEventArgs args) {
    return ((Universe)sender).CreateMissingAssembly(args.Name);
  }
}

When you don't handle the Universe.AssemblyResolve event (or non of the handlers return an assembly), IKVM.Reflection will fall back to using System.Reflection.Assembly.ReflectionOnlyLoad() and then use the Location property of the returned assembly and load the assembly from there.

If you do handle the Universe.AssemblyResolve event, you can either find the assembly somewhere and load it, or use Universe.CreateMissingAssembly() to create a placeholder Assembly that will automatically resolve all types and members that it is expected to contain (based on references from loaded assemblies that are inspected).

When you're reflecting over the members you can encounter types and members from the missing assemblies and you should be prepared to handle these because many operations are not allowed on them (since there is no type or member definition, a lot of information simply isn't available). You can detect these missing types or members by looking at the MemberInfo.__IsMissing property.

Friday, 16 March 2012 13:26:07 (W. Europe Standard Time, UTC+01:00)  #    Comments [2]
Friday, 16 March 2012 17:35:27 (W. Europe Standard Time, UTC+01:00)
How does Cecil fit in this picture... is this it's replacement?
Jed
Saturday, 17 March 2012 11:54:07 (W. Europe Standard Time, UTC+01:00)
No, it's not a replacement for Cecil. There is definitely overlap, but both have a different focus. The focus of IKVM.Reflection is obviously compatibility with System.Reflection (to allow code bases such as IKVM and Mono's C# compiler that can be compiled to use either System.Reflection or IKVM.Reflection) and I think that the sweetspot of Cecil is manipulating existing assemblies (i.e. load an assembly make some modification to it via Cecil's object model and then write it out again). With IKVM.Reflection this would be very much more work.
Name
E-mail
Home page

I apologize for the lameness of this, but the comment spam was driving me nuts. In order to be able to post a comment, you need to answer a simple question. Hopefully this question is easy enough not to annoy serious commenters, but hard enough to keep the spammers away.

Anti-Spam Question: What method on java.lang.System returns an object's original hashcode (i.e. the one that would be returned by java.lang.Object.hashCode() if it wasn't overridden)? (case is significant)

Answer:  
Comment (HTML not allowed)  

Live Comment Preview