         self.hashValue = hash(self.type, self.name, self.container)
     }
     
-    public let hashValue: Int
-}
-
-public func ==(lhs: Key, rhs: Key) -> Bool {
+    public init<T, N: Hashable>(type: T.Type, name: N) {
+        self.init(type: type, name: name, container: Name.default)
+    }
+    
+    public init<T, C: Hashable>(type: T.Type, container: C) {
+        self.init(type: type, name: Name.default, container: container)
+    }
+}
+
+extension Set where Element == AnyKey {
+    public func typed<T>() -> Set<Key<T>> {
+        return Set<Key<T>>(flatMap{ Key($0) })
+    }
+}
+
+public func ==(lhs: AnyKey, rhs: AnyKey) -> Bool {
     if lhs.hashValue != rhs.hashValue { return false }
     if lhs.type != rhs.type { return false }
     if lhs.name != rhs.name { return false }
+    if lhs.container != rhs.container { return false }
+    return true
+}
+
+public struct Key<T>: Keyed, Hashable {
+    public let type: String
+    public let name: AnyHashable
+    public let container: AnyHashable
+    public let hashValue: Int
+    
+    public init<N: Hashable, C: Hashable>(name: N, container: C) {
+        self.type = String(reflecting: T.self)
+        self.name = name
+        self.container = container
+        self.hashValue = hash(self.type, self.name, self.container)
+    }
+    
+    public init<N: Hashable>(name: N) {
+        self.init(name: name, container: Name.default)
+    }
+    
+    public init<C: Hashable>(container: C) {
+        self.init(name: Name.default, container: container)
+    }
+    
+    public init() {
+        self.init(name: Name.default, container: Name.default)
+    }
+    
+    public init?(_ key: AnyKey) {
+        if key.type != String(reflecting: T.self) { return nil }
+        self.type = key.type
+        self.name = key.name
+        self.container = key.container
+        self.hashValue = hash(self.type, self.name, self.container)
+    }
+    
+}
+
+public func ==<T>(lhs: Key<T>, rhs: Key<T>) -> Bool {
+    if lhs.hashValue != rhs.hashValue { return false }
+    if lhs.name != rhs.name { return false }
+    if lhs.container != rhs.container { return false }
     return true
 }
 

    /**
     Returns true if a registration exists for the given key.
     */
    public static func exists(key: Key) -> Bool {
        return lock.read { return registrations[key] != nil }
    }
    

     Returns true if a key with the given type, name, and container exists.
    */
    public static func exists<T, N: Hashable, C: Hashable, M>(type: T.Type, name: N, container: C, metafilter: @escaping Metafilter<M>) -> Bool {
        return exists(key: AnyKey(type: type, name: name, container: container), metafilter: metathunk(metafilter))
    }

    /**
     Returns true if a key with the given type, name, and container exists.
     */
    public static func exists<T, N: Hashable, C: Hashable>(type: T.Type, name: N, container: C) -> Bool {
        return exists(key: AnyKey(type: type, name: name, container: container))
    }
    
    /**
