diff --git a/.travis.yml b/.travis.yml
index d254bd80..0435df42 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,7 @@ sudo: false
 python:
 - 2.7
 install:
-- pip install pytest pytest-cov coveralls flake8 six
+- pip install pytest pytest-cov coveralls flake8 six blinker
 - pip install git+https://github.com/dittos/graphqllib.git # Last version of graphqllib
 - pip install graphql-relay
 - python setup.py develop
diff --git a/graphene/__init__.py b/graphene/__init__.py
index 42442952..6024313c 100644
--- a/graphene/__init__.py
+++ b/graphene/__init__.py
@@ -26,3 +26,7 @@ from graphene.core.types import (
 from graphene.decorators import (
     resolve_only_args
 )
+
+from graphene.relay import (
+    Relay
+)
diff --git a/graphene/core/fields.py b/graphene/core/fields.py
index 876416b1..d37fed1d 100644
--- a/graphene/core/fields.py
+++ b/graphene/core/fields.py
@@ -1,4 +1,3 @@
-import inspect
 from graphql.core.type import (
     GraphQLField,
     GraphQLList,
@@ -9,8 +8,8 @@ from graphql.core.type import (
     GraphQLID,
     GraphQLArgument,
 )
-from graphene.core.types import ObjectType, Interface
 from graphene.utils import cached_property
+from graphene.core.utils import get_object_type
 
 class Field(object):
     def __init__(self, field_type, resolve=None, null=True, args=None, description='', **extra_args):
@@ -45,16 +44,11 @@ class Field(object):
 
     @cached_property
     def type(self):
-        field_type = self.field_type
-        _is_class = inspect.isclass(field_type)
-        if _is_class and issubclass(field_type, ObjectType):
-            field_type = field_type._meta.type
-        elif isinstance(field_type, Field):
-            field_type = field_type.type
-        elif field_type == 'self':
-            field_type = self.object_type._meta.type
+        if isinstance(self.field_type, Field):
+            field_type = self.field_type.type
+        else:
+            field_type = get_object_type(self.field_type, self.object_type)
         field_type = self.type_wrapper(field_type)
-
         return field_type
 
     def type_wrapper(self, field_type):
diff --git a/graphene/core/options.py b/graphene/core/options.py
index f55cd494..5a016dff 100644
--- a/graphene/core/options.py
+++ b/graphene/core/options.py
@@ -1,6 +1,8 @@
 from graphene.utils import cached_property
 
-DEFAULT_NAMES = ('description', 'name', 'interface', 'type_name', 'interfaces',  'proxy')
+DEFAULT_NAMES = ('description', 'name', 'interface',
+                 'type_name', 'interfaces',  'proxy')
+
 
 class Options(object):
     def __init__(self, meta=None):
@@ -62,7 +64,7 @@ class Options(object):
 
     @cached_property
     def fields_map(self):
-        return {f.field_name:f for f in self.fields}
+        return {f.field_name: f for f in self.fields}
 
     @cached_property
     def type(self):
diff --git a/graphene/core/types.py b/graphene/core/types.py
index 250559e5..a5645b16 100644
--- a/graphene/core/types.py
+++ b/graphene/core/types.py
@@ -8,8 +8,10 @@ from graphql.core.type import (
 )
 from graphql.core import graphql
 
+from graphene import signals
 from graphene.core.options import Options
 
+
 class ObjectTypeMeta(type):
     def __new__(cls, name, bases, attrs):
         super_new = super(ObjectTypeMeta, cls).__new__
@@ -20,7 +22,10 @@ class ObjectTypeMeta(type):
 
         module = attrs.pop('__module__')
         doc = attrs.pop('__doc__', None)
-        new_class = super_new(cls, name, bases, {'__module__': module, '__doc__': doc})
+        new_class = super_new(cls, name, bases, {
+            '__module__': module,
+            '__doc__': doc
+        })
         attr_meta = attrs.pop('Meta', None)
         if not attr_meta:
             meta = getattr(new_class, 'Meta', None)
@@ -51,7 +56,7 @@ class ObjectTypeMeta(type):
             # moment).
             for field in parent_fields:
                 if field.field_name in field_names:
-                    raise FieldError(
+                    raise Exception(
                         'Local field %r in class %r clashes '
                         'with field of similar name from '
                         'base class %r' % (field.field_name, name, base.__name__)
@@ -61,8 +66,12 @@ class ObjectTypeMeta(type):
                 new_class._meta.interfaces.append(base)
             # new_class._meta.parents.extend(base._meta.parents)
 
+        new_class._prepare()
         return new_class
 
+    def _prepare(cls):
+        signals.class_prepared.send(cls)
+
     def add_to_class(cls, name, value):
         # We should call the contribute_to_class method only if it's bound
         if not inspect.isclass(value) and hasattr(value, 'contribute_to_class'):
@@ -73,15 +82,17 @@ class ObjectTypeMeta(type):
 
 class ObjectType(six.with_metaclass(ObjectTypeMeta)):
     def __init__(self, instance=None):
+        signals.pre_init.send(self.__class__, instance=instance)
         self.instance = instance
+        signals.post_init.send(self.__class__, instance=self)
 
     def get_field(self, field):
         return getattr(self.instance, field, None)
 
     def resolve(self, field_name, args, info):
         if field_name not in self._meta.fields_map.keys():
-            raise Exception('Field %s not found in model'%field_name)
-        custom_resolve_fn = 'resolve_%s'%field_name
+            raise Exception('Field %s not found in model' % field_name)
+        custom_resolve_fn = 'resolve_%s' % field_name
         if hasattr(self, custom_resolve_fn):
             resolve_fn = getattr(self, custom_resolve_fn)
             return resolve_fn(args, info)
@@ -104,13 +115,13 @@ class ObjectType(six.with_metaclass(ObjectTypeMeta)):
                 cls._meta.type_name,
                 description=cls._meta.description,
                 resolve_type=cls.resolve_type,
-                fields=lambda: {name:field.field for name, field in fields.items()}
+                fields=lambda: {name: field.field for name, field in fields.items()}
             )
         return GraphQLObjectType(
             cls._meta.type_name,
             description=cls._meta.description,
             interfaces=[i._meta.type for i in cls._meta.interfaces],
-            fields=lambda: {name:field.field for name, field in fields.items()}
+            fields=lambda: {name: field.field for name, field in fields.items()}
         )
 
 
@@ -125,7 +136,7 @@ class Schema(object):
         self.query = query
         self.query_type = query._meta.type
         self._schema = GraphQLSchema(query=self.query_type, mutation=mutation)
-    
+
     def execute(self, request='', root=None, vars=None, operation_name=None):
         return graphql(
             self._schema,
diff --git a/graphene/core/utils.py b/graphene/core/utils.py
new file mode 100644
index 00000000..2441e644
--- /dev/null
+++ b/graphene/core/utils.py
@@ -0,0 +1,30 @@
+import inspect
+
+from graphene.core.types import ObjectType
+from graphene import signals
+
+registered_object_types = []
+
+
+def get_object_type(field_type, object_type=None):
+    _is_class = inspect.isclass(field_type)
+    if _is_class and issubclass(field_type, ObjectType):
+        field_type = field_type._meta.type
+    elif isinstance(field_type, basestring):
+        if field_type == 'self':
+            field_type = object_type._meta.type
+        else:
+            object_type = get_registered_object_type(field_type)
+            field_type = object_type._meta.type
+    return field_type
+
+
+def get_registered_object_type(name):
+    for object_type in registered_object_types:
+        if object_type._meta.type_name == name:
+            return object_type
+    return None
+
+@signals.class_prepared.connect
+def object_type_created(sender):
+    registered_object_types.append(sender)
diff --git a/graphene/relay/__init__.py b/graphene/relay/__init__.py
index e69de29b..80feb122 100644
--- a/graphene/relay/__init__.py
+++ b/graphene/relay/__init__.py
@@ -0,0 +1,2 @@
+class Relay(object):
+	pass
diff --git a/graphene/signals.py b/graphene/signals.py
new file mode 100644
index 00000000..954d02a1
--- /dev/null
+++ b/graphene/signals.py
@@ -0,0 +1,5 @@
+from blinker import Signal
+
+class_prepared = Signal()
+pre_init = Signal()
+post_init = Signal()
diff --git a/setup.py b/setup.py
index b5222dc0..705d1ac3 100644
--- a/setup.py
+++ b/setup.py
@@ -48,6 +48,7 @@ setup(
 
     install_requires=[
         'six',
+        'blinker',
         'graphqllib',
         'graphql-relay'
     ],
diff --git a/tests/starwars/schema.py b/tests/starwars/schema.py
index 1a7e570d..018a1fc8 100644
--- a/tests/starwars/schema.py
+++ b/tests/starwars/schema.py
@@ -18,7 +18,7 @@ def wrap_character(character):
 class Character(graphene.Interface):
     id = graphene.IDField()
     name = graphene.StringField()
-    friends = graphene.ListField('self')
+    friends = graphene.ListField('Character')
     appearsIn = graphene.ListField(Episode)
 
     def resolve_friends(self, args, *_):
diff --git a/tests/starwars_relay/schema.py b/tests/starwars_relay/schema.py
new file mode 100644
index 00000000..1a7e570d
--- /dev/null
+++ b/tests/starwars_relay/schema.py
@@ -0,0 +1,61 @@
+import graphene
+from graphene import resolve_only_args
+
+from .data import getHero, getHuman, getCharacter, getDroid, Human as _Human, Droid as _Droid
+
+Episode = graphene.Enum('Episode', dict(
+    NEWHOPE = 4,
+    EMPIRE = 5,
+    JEDI = 6
+))
+
+def wrap_character(character):
+    if isinstance(character, _Human): 
+        return Human(character)
+    elif isinstance(character, _Droid):
+        return Droid(character)
+
+class Character(graphene.Interface):
+    id = graphene.IDField()
+    name = graphene.StringField()
+    friends = graphene.ListField('self')
+    appearsIn = graphene.ListField(Episode)
+
+    def resolve_friends(self, args, *_):
+        return [wrap_character(getCharacter(f)) for f in self.instance.friends]
+
+class Human(Character):
+    homePlanet = graphene.StringField()
+
+
+class Droid(Character):
+    primaryFunction = graphene.StringField()
+
+
+class Query(graphene.ObjectType):
+    hero = graphene.Field(Character,
+        episode = graphene.Argument(Episode)
+    )
+    human = graphene.Field(Human,
+        id = graphene.Argument(graphene.String)
+    )
+    droid = graphene.Field(Droid,
+        id = graphene.Argument(graphene.String)
+    )
+
+    @resolve_only_args
+    def resolve_hero(self, episode):
+        return wrap_character(getHero(episode))
+
+    @resolve_only_args
+    def resolve_human(self, id):
+        return wrap_character(getHuman(id))
+        if human:
+            return Human(human)
+
+    @resolve_only_args
+    def resolve_droid(self, id):
+        return wrap_character(getDroid(id))
+
+
+Schema = graphene.Schema(query=Query)
diff --git a/tox.ini b/tox.ini
index 09e27276..735a042d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,6 +6,8 @@ deps=
     pytest>=2.7.2
     django>=1.8.0,<1.9
     flake8
+    six
+    blinker
     singledispatch
 commands=
     py.test