  SOFTWARE.
  */
 
-private protocol InstanceContainer : class {
-    associatedtype InstanceType
+private struct Weak<Instance: AnyObject> {
+    weak var instance: Instance?
     
-    var instance: InstanceType? { get }
-}
-
-private class StrongContainer<C> : InstanceContainer {
-    var strongInstance: C?
-    
-    var instance: C? {
-        return strongInstance
-    }
-    
-    init(instance: C) {
-        strongInstance = instance
+    init(_ instance: Instance) {
+        self.instance = instance
     }
 }
 
-private class WeakContainer<C: AnyObject> : InstanceContainer {
-    weak var weakInstance: C?
-    
-    var instance: C? {
-        return weakInstance
+open class DependencyFactory {
+    enum Lifecyle {
+        case shared
+        case weakShared
+        case unshared
+        case scoped
     }
     
-    init(instance: C) {
-        weakInstance = instance
-    }
-}
-
-private func ==(lhs: DependencyFactory.InstanceKey, rhs: DependencyFactory.InstanceKey) -> Bool {
-    return (lhs.lifecycle == rhs.lifecycle) && (lhs.name == rhs.name)
-}
-
-open class DependencyFactory {
-    fileprivate enum Lifecyle : String, CustomStringConvertible {
-        case Shared = "shared"
-        case WeakShared = "weakShared"
-        case Unshared = "unshared"
-        case Scoped = "scoped"
-        
-        var description: String {
-            return self.rawValue
-        }
-    }
-    
-    fileprivate struct InstanceKey : Hashable, CustomStringConvertible {
+    struct InstanceKey : Hashable, CustomStringConvertible {
         let lifecycle: Lifecyle
         let name: String
         

        let instance = factory()
        instanceStack.removeLast()
        
        let container = containerFactory(instance)
        instancePool[name] = container
        
        if let configure = configure {
            configureStack.append({configure(instance)})

    
    public final func scoped<T>(name: String = #function, _ factory: @autoclosure () -> T, configure: ((T) -> Void)? = nil) -> T {
        return inject(
            lifecyle: .scoped,
            name: name,
            instances: &scopedInstances,
            factory: factory,
            configure: configure
        )
    }
    
    private final func inject<T>(lifecyle: Lifecyle, name: String, instances: inout [String:Any], factory: () -> T, configure: ((T) -> Void)?) -> T {
        if let instance = instances[name] as? T {
            return instance
        }
        
        let key = InstanceKey(lifecycle: lifecyle, name: name)
        
        if lifecyle != .unshared && instanceStack.contains(key) {
            fatalError("Circular dependency from one of \(instanceStack) to \(key) in initializer")
        }
        
