将反射对象的cast属性恢复为其原始类型

时间:2015-02-07 19:07:41

标签: swift reflection generics

所有这些都是关于包装任何对象或类型(= Any)并且能够检查类型是否在以后相等。使用类作为类型和值的包装可以正常工作。我的问题是我想抛出一个对象,通过反射找到它的属性,并为每个具有该属性的(包装)类型的属性创建一个包装器。问题是反射的属性总是类型为Any - 我需要转换为它们的实际类型(例如String)。

示例将清除:

// Functions to check equality of Types
func unsafeGetTypeId(type: Any.Type) -> uintptr_t {
    return unsafeBitCast(type, uintptr_t.self)
}
func areOfSameType(v1: Any, v2: Any) -> Bool {
    return unsafeGetTypeId(reflect(v1).valueType) == unsafeGetTypeId(reflect(v2).valueType)
}

class ZType {

}

class ZTypeT<T> {
    var value: Any?
    init() {

    }
    init( value: T ) {
        self.value = value
    }
}

class SampleClass {
    var sampleProperty : String
    init( aString: String ) {
        self.sampleProperty = aString
    }
}

var sample = SampleClass(aString: "Hans")

var t1 = ZTypeT<String>()
var t2 = ZTypeT(value: sample.sampleProperty)
areOfSameType(t1, t2) // true

var mirror = reflect(sample)
for var index=0; index<mirror.count; ++index {
    let (propertyName, childMirror) = mirror[index]

    var tTestAgainst = ZTypeT<String>()

    // This is obviously of type Any so it won`t be ZTypeT<String>() but ZTypeT<Any>()
    var tMirrorProp = ZTypeT(value: childMirror.value)
    areOfSameType(tMirrorProp, tTestAgainst) // false

    // So how could i cast the value back to it`s type? This would work but it should be generic : i don`t know the type beforehand
    var tMirrorPropCasted = ZTypeT(value: childMirror.value as String)
    areOfSameType(tMirrorPropCasted, tTestAgainst) // false
}

正如您所看到的那样,直到tMirrorProp才能正常工作,因为它不是String类型。如果我施展它,我的支票将再次成立 - 但我不能在不知道类型的情况下施放。有没有人知道解决这个问题的解决方案。使用Swift-Classes的解决方案是首选,但与NSObject一起使用的解决方案仍然是有趣的。

1 个答案:

答案 0 :(得分:0)

正如您已经说过的,实例化正确类型的唯一方法是将childMirror.value强制转换为正确的类型。你可以通过为每种类型添加一个开关来做到这一点。然后使用NSStringFromClass(tMirrorPropCasted.dynamicType)比较对象。你会得到类似的东西:

var tMirrorPropCasted : ZTypeT<Any>

var theValue = anyValue
let mi:MirrorType = reflect(theValue)
if mi.disposition == .Optional {
   if mi.count == 0 { // Optional.None
      theValue = NSNull() 
   } else {
      let (name,some) = mi[0]
      theValue = some.value
   }
}

switch(theValue) {
        case let intValue as Int:
            tMirrorPropCasted = ZTypeT(value: childMirror.value as Int)
        case let doubleValue as Double:
            tMirrorPropCasted = ZTypeT(value: childMirror.value as Double)
        case let stringValue as String:
            tMirrorPropCasted = ZTypeT(value: childMirror.value as String)
        case let boolValue as Bool:
            tMirrorPropCasted = ZTypeT(value: childMirror.value as Bool)
        case let anyvalue as NSObject:
            tMirrorPropCasted = ZTypeT(value: childMirror.value as NSObject)
        default:
            tMirrorPropCasted = ZTypeT(value: childMirror.value)
        }

但是,您还可以检查值属性的类型,而不是检查对象的类型。该属性仍将包含其原始类型的信息。所以你能做的就是测试

if NSStringFromClass(tTestAgainst.value.dynamicType) == NSStringFromClass(tMirrorProp.value.dynamicType) {
   NSLog("Same type")
}