diff --git a/gstreamer-sharp/Application.cs b/gstreamer-sharp/Application.cs
index 2084c42..c7468de 100644
--- a/gstreamer-sharp/Application.cs
+++ b/gstreamer-sharp/Application.cs
@@ -14,6 +14,7 @@ using System;
 using System.Reflection;
 using System.IO;
 using System.Runtime.InteropServices;
+using System.Collections.Generic;
 
 namespace Gst {
 
@@ -57,56 +58,65 @@ namespace Gst {
       gst_deinit();
     }
 
-    private static System.Type GstResolveType (Gst.GLib.GType gtype, string gtype_name) {
-      Assembly[] assemblies = (Assembly[]) AppDomain.CurrentDomain.GetAssemblies ().Clone ();
+    private static Dictionary<int,bool> AssemblyTypesInCache = new Dictionary<int,bool> ();
+    private static Dictionary<string,Type> TypeCache = new Dictionary<string,Type> ();
+
+    // Recursively check for types with GTypeNameAttribute and put them in TypeCache,
+    // but only if gstreamer-sharp is in the chain of referenced assemblies.
+    private static void PutAssemblyTypesInCache (Assembly asm)
+    {
+      // If already visited, return immediately
+      if (AssemblyTypesInCache.ContainsKey(asm.GetHashCode ()))
+        return;
+
+      // Add with false to avoid chasing circular dependencies
+      AssemblyTypesInCache.Add (asm.GetHashCode (), false);
+
+      // Result is true for gstreamer-sharp or if a referenced assembly results in true
+      bool result = asm.GetName().Name.Equals("gstreamer-sharp");
+
+      foreach (AssemblyName ref_name in asm.GetReferencedAssemblies ()) {
+        try {
+          Assembly ref_asm = Assembly.Load (ref_name);
+          PutAssemblyTypesInCache (ref_asm);
+          result = result | AssemblyTypesInCache[ref_asm.GetHashCode ()];
+        } catch {
+          /* Failure to load a referenced assembly is not an error */
+        }
+      }
 
-      foreach (Assembly asm in assemblies) {
-        Type[] ts = asm.GetTypes ();
+      // Add types with GTypeNameAttribute in TypeCache
+      if (result) {
+        AssemblyTypesInCache[asm.GetHashCode ()] = true;
+        Type[] ts;
+        try {
+          ts = asm.GetTypes ();
+        } catch (ReflectionTypeLoadException e) {
+          ts = e.Types;
+        }
         foreach (Type t in ts) {
-          if (t.IsDefined (typeof (Gst.GTypeNameAttribute), false)) {
+          if (t != null && t.IsDefined (typeof (GTypeNameAttribute), false)) {
             GTypeNameAttribute gattr = (GTypeNameAttribute) Attribute.GetCustomAttribute (t, typeof (GTypeNameAttribute), false);
-            if (gtype_name.Equals (gattr.TypeName)) {
-              return t;
-            }
+            TypeCache[gattr.TypeName] = t;
           }
         }
       }
+    }
 
-      foreach (Assembly asm in assemblies) {
-        foreach (AssemblyName ref_name in asm.GetReferencedAssemblies ()) {
-          try {
-            Assembly ref_asm;
-            if (asm.Location != String.Empty)
-            {
-                string asm_file = Path.Combine(Path.GetDirectoryName(asm.Location), ref_name.Name + ".dll");
-                if (File.Exists(asm_file))
-                    ref_asm = Assembly.LoadFrom(asm_file);
-                else
-                    ref_asm = Assembly.Load(ref_name);
-            }
-            else
-                ref_asm = Assembly.Load(ref_name);
-
-            Type[] ts = asm.GetTypes ();
-            foreach (Type t in ts) {
-              if (t.IsDefined (typeof (Gst.GTypeNameAttribute), false)) {
-                GTypeNameAttribute gattr = (GTypeNameAttribute) Attribute.GetCustomAttribute (t, typeof (GTypeNameAttribute), false);
-                if (gtype_name.Equals (gattr.TypeName)) {
-                  return t;
-                }
-              }
-            }
-
-          } catch (Exception) {
-            /* Failure to load a referenced assembly is not an error */
-          }
-        }
-      }
+    private static System.Type GstResolveType (Gst.GLib.GType gtype, string gtype_name) {
+      // Make sure all currently loaded assemblies are in the TypeCache
+      System.Array.ForEach((Assembly[]) AppDomain.CurrentDomain.GetAssemblies ().Clone (), Application.PutAssemblyTypesInCache);
+
+      // Return the managed type
+      if (TypeCache.ContainsKey (gtype_name))
+        return TypeCache[gtype_name];
 
       return null;
     }
 
     private static void RegisterManagedTypes() {
+      // Load types in TypeCache to speed up later invocations of GstResolveType
+      System.Array.ForEach((Assembly[]) AppDomain.CurrentDomain.GetAssemblies ().Clone (), Application.PutAssemblyTypesInCache);
       Gst.GLib.GType.ResolveType += GstResolveType;
 
       Gst.GLib.GType.Register (Fraction.GType, typeof (Fraction));
@@ -121,6 +131,11 @@ namespace Gst {
       Gst.GLib.GType.Register (Structure.GType, typeof (Structure));
       Gst.GLib.GType.Register (TagList.GType, typeof (TagList));
       Gst.GLib.GType.Register (MiniObject.GType, typeof (MiniObject));
+      Gst.GLib.GType.Register (Bus.GType, typeof (Bus));
+      Gst.GLib.GType.Register (Pad.GType, typeof (Pad));
+      Gst.GLib.GType.Register (GhostPad.GType, typeof (GhostPad));
+      Gst.GLib.GType.Register (Message.GType, typeof (Message));
+      Gst.GLib.GType.Register (SystemClock.GType, typeof (SystemClock));
 
       GtkSharp.GstreamerSharp.ObjectManager.Initialize ();
     }
