    var modelWriteKeyStrings: [String] { get }
    var viewReadKeyStrings: [String] { get }
    var viewWriteKeyStrings: [String] { get }
-   
-   func bindings(for keyString: String) -> [Binding]
 }
 
 public extension StringConductionModelType {

   open var viewReadKeys: [Key] { return viewReadOnlyKeys + viewReadWriteKeys }
   open var viewWriteKeys: [Key] { return viewReadWriteKeys + viewWriteOnlyKeys }
   
   public func bindings(for key: Key) -> [Binding] {
      let bindings = modelBindings.filter(key: key)
      guard bindings.isEmpty else { return bindings }
      return [Binding(key: key, target: self, targetKey: key)]
   }
   
   public func bindings<MapKey: IncKVKeyType>(for key: Key, mappedTo mapKey: MapKey) -> [Binding] {
      let bindings = modelBindings.filter(key: key)
      guard bindings.isEmpty else { return bindings.map(firstKey: key, toSecondKey: mapKey) }
      return [Binding(key: mapKey, target: self, targetKey: key)]
   }
   
   // MARK: - Bindable Protocol
   public var bindingBlocks: [Key : [((targetObject: AnyObject, rawTargetKey: String)?, Any?) throws -> Bool?]] = [:]
   public var keysBeingSet: [Key] = []
   
   public func value(for key: Key) -> Any? {
      guard modelReadKeys.contains(key) else { return conductedValue(for: key) }
      let bindings = modelBindings.filter(key: key)
      return bindings.last?.targetValue
   }
   
   public func setOwn(value: Any?, for key: Key) throws {
      guard modelWriteKeys.contains(key) else { try set(conductedValue: value, for: key); return }
      let bindings = modelBindings.filter(key: key)
      try bindings.forEach { try $0.set(targetValue: value) }
   }
}

   open var viewReadWriteKeys: [Key] { return [] }
   open var viewWriteOnlyKeys: [Key] { return [] }
   
   // MARK: - Public
   public func value<T>(for key: Key, default defaultValue: T?) -> T? {
      return value(for: key) as? T ?? defaultValue
   }
   
   // MARK: - Init
   public init() {}
   
   // MARK: - Model Binding
   public func bind(model: StringBindable) throws {
      let modelBindings = modelKeys.map { return Binding(key: $0, target: model, targetKey: $0) }
      try bind(modelBindings: modelBindings)
   }
   
   public func bind(modelBindings: [Binding]) throws {
      try modelReadOnlyKeys.forEach {
         try modelBindings.filter(key: $0).forEach { try $0.target.bindOneWay(key: $0.targetKey, to: self, key: $0.key) }
      }
      try modelReadWriteKeys.forEach {
         try modelBindings.filter(key: $0).forEach { try self.bind($0) }
      }
      try modelWriteOnlyKeys.forEach {
         try modelBindings.filter(key: $0).forEach { try self.bindOneWay(key: $0.key, to: $0.target, key: $0.targetKey) }
      }
   }

   public func unbind(model: StringBindable) {
      let modelBindings = modelKeys.map { return Binding(key: $0, target: model, targetKey: $0) }
      unbind(modelBindings: modelBindings)
   }
   
   public func unbind(modelBindings: [Binding]) {
      modelReadOnlyKeys.forEach {
         modelBindings.filter(key: $0).forEach { $0.target.unbindOneWay(key: $0.targetKey, to: self, key: $0.key) }
      }
      modelReadWriteKeys.forEach {
         modelBindings.filter(key: $0).forEach { self.unbind($0) }
      }
      modelWriteOnlyKeys.forEach {
         modelBindings.filter(key: $0).forEach { self.unbindOneWay(key: $0.key, to: $0.target, key: $0.targetKey) }
      }
   }

   // MARK: - Subclass Hooks
   open func conductedValue(_ value: Any?, for key: Key) -> Any? { return value }
   open func set(conductedValue value: Any?, for key: Key) throws -> Any? { return value }
   
   // MARK: - ConductionModelType Protocol
   open var modelReadKeys: [Key] { return modelReadOnlyKeys + modelReadWriteKeys }
