[英]How to set a derived object to a base class variable when the baseclass is generic
[英]How to use derived object in list of baseclass for generic extension
哦,男孩,我在這個問題上花了很多時間...
我想做的是克隆一個GameObject
類型的對象,該對象還包含一個Component
列表。 克隆GameObject
類型沒有任何問題,但似乎此列表是一個問題,因為它是克隆的,但不是其內容。 內容不被復制,而是被存儲。
盡管我想像使用游戲對象一樣克隆這些組件,但由於我的系統,這是不可能的。
組件連接到GameObject
並基本上定義GameObject
。 例如,如果我想創建一種用於控制GameObject
的方式,則可以創建一個名為PlayerController
Component
,該Component
將從基本類型Component
派生而來,如下所示:
class Component
{
//The gameobject this component is attached to
public GameObject gameObject { get; set;}
public virtual void Update()
{
//..
}
}
class PlayerController : Component
{
override Update()
{
Move();
//..
}
public void Move()
{
//...
}
}
我克隆GameObject的方式是這樣的方法:
public GameObject Clone(Vector2 position, float scale)
{
GameObject source = this;
GameObject clone = new GameObject();
//Get all properties of a GameObject
var srcProperties = TypeDescriptor.GetProperties(typeof(GameObject)).Cast<PropertyDescriptor>();
//Assign all properties from the source to the clone
foreach (var srcProperty in srcProperties)
{
srcProperty.SetValue(clone, srcProperty.GetValue(source));
}
//Clone all components from source and add them to the clone
if (source.components.Count > 0)
{
for (int i = source.components.Count - 1; i >= 0; i--)
{
var srcComp = source.components[i];
var compClone = srcComp.CloneComponent();
clone.components.Add(compClone);
}
}
clone.position = position;
clone.scale = scale;
AllGameObjects.Add(clone);
if (clone.components.Count > 0)
{
//Set the owner gameobjects and start the components
for (int i = clone.components.Count - 1; i >= 0; i--)
{
var comp = clone.components[i];
comp.gameObject = clone;
comp.Start();
}
}
return clone;
}
第17行的CloneComponent()
方法var compClone = srcComp.CloneComponent();
是一個通用擴展方法,如下所示:
public static TComponent CloneComponent<TComponent>(this TComponent source) where TComponent : Component, new()
{
TComponent clone = new TComponent();
var srcProperties = TypeDescriptor.GetProperties(typeof(TComponent)).Cast<PropertyDescriptor>();
foreach (var srcProperty in srcProperties)
{
srcProperty.SetValue(clone, srcProperty.GetValue(source));
}
return clone;
}
如果源不是從Component
列表中獲取的,則此方法可以正常工作,似乎可以將其類型轉換為僅當用作參數時才執行的根類型。 顯然,這將導致TComponent
的類型為Component
,而不是克隆源,而是將其轉換為根類型,並僅從中克隆屬性。
我要的是一種繞過此方法的方法,或者在用作參數時不轉換為根類型的方法?
編輯:
參數source
的類型將是正確的類型,但是當source參數作為list的參數給出時, TComponent
的類型將始終是Component
。 您可能會認為我在解釋這個錯誤,但是我認為這和您一樣奇怪。 我唯一能想到的是它是一個錯誤,我認為這不太可能。
最終編輯:
非常感謝@Philipp使用Activator.CreateInstance
的建議。 這就是我更改CloneComponent()
方法的方式:
public static Component CloneComponent(this Component source)
{
var clone = Activator.CreateInstance(source.GetType());
var srcProperties = TypeDescriptor.GetProperties(source.GetType()).Cast<PropertyDescriptor>();
foreach (var srcProperty in srcProperties)
{
srcProperty.SetValue(clone, srcProperty.GetValue(source));
}
return (Component)clone;
}
source.GetType()
而不是typeof(TComponent)
應該返回實際的(繼承的)類型,您可以使用Activator.CreateInstance()
創建實例。 另外,您始終可以對整個樹進行二進制序列化,然后再次進行反序列化,從而為對象圖提供了完整的深層克隆。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.