2017-06-06 41 views
0

考慮以下問題: 我想在運行時用值填充類型爲T的數組。我能夠獲得所有的GameObjects(在這裏討論Unity3D),它們持有這些實例之一。這些GameObjects都在結果數組中。 GetComponent方法允許從gameObject中提取T的實例,但自動將其轉換爲Ts基類組件藍圖包含有關綁定目標的信息,例如數組的FieldInfo。使用反射來填充派生類的數組與基類數組

當前的代碼看起來是這樣的:

var arrayOfBaseClass = 
    (
     from instance 
     in results 
     select instance.GetComponent(blueprint.Field.FieldType.GetElementType())) 
    .ToArray(); 
// Missing Step here 
blueprint.Field.SetValue(o, arrayOfBaseClass); 

的SetValue拋出現在的ArgumentException:對象類型UnityEngine.Component []不能被轉換爲目標類型:VEL.Input.ActionSignalReceiver []

附加信息arrayOfBaseClass實際上是一個T的instaces數組,只是通過GetComponent強制轉換爲基類型。如果我事先知道T,那麼手動投射到T將會工作並解決這個問題。可悲的T是事先不知道,並且可能會在不同類型之間變化(但都來自組件)

現在的問題是,如果有一種方法使用FieldInfo的信息將數組轉換回其最派生類型。

+0

做的是在重複提到的陣列,並且你在每一個實例重做。 – HimBromBeere

+0

我不認爲這是鏈接問題的重複。首先,這不是關於將任意類轉換爲基類的問題,其次,這個問題是專門詢問關於「SetValue」的反射。我使用的類是派生類的實例,我只需要通過SetValue通過數組綁定它們。 – floAr

+0

從你的代碼中很難看出結果,arrayOfDerivedClass和arrayOfBaseClass實際是什麼。一個數組沒有'Field'屬性。 – HimBromBeere

回答

0

想通了一些試驗和錯誤,會在下面的解釋中發佈相關代碼。 由於我們在反思中工作,我們需要一種方法來傳遞我們想要使用的目標類型。在這種情況下,我們可以通過在運行時構造一個通用方法來實現。因此,我們首先聲明一個通用函數,它接受一個目標對象,一個fieldInfo(事先檢查它是一個數組字段)和一個對象數組。這些對象被強制轉換爲目標類型T的,然後分配到外地:

public void BindToTypedArray<T> (object bindingTarget, FieldInfo field, object[] values) 
    { 
     var typedArray = from v in values select (T)v; 
     field.SetValue(bindingTarget, typedArray.ToArray()); 
    } 

要調用這個函數,我們需要知道的類型T,但是反射通過在運行時提供了一個方法來創建一個類型化的通用方法MakeGenericMethod。所以我們做在上面的例子是什麼,我們創建一個自定義我們所產生的對象數組中輸入上面的功能和飼料的實例:

var arrayOfBaseClass = 
     (
      from instance 
      in results 
      select instance.GetComponent(blueprint.Field.FieldType.GetElementType())) 
     .ToArray(); 

    // NEWCODE -------------------------------------------------------- 
    MethodInfo bindArray= typeof(DataGlueController).GetMethod("BindToTypedArray"); 
    MethodInfo bindArrayTyped=bindArray.MakeGenericMethod(blueprint.Field.FieldType.GetElementType()); 
    bindArrayTyped.Invoke(this, new object[] { o, blueprint.Field, arrayOfBaseClass }); 
    // END NEWCODE ---------------------------------------------------- 

    // blueprint.Field.SetValue(o, arrayOfBaseClass); <- this is done in the BindToTypedArray function