我目前正在尝试克隆我的XNA项目中的自定义类型,我称之为“#34; Component"”,看起来像这样。
public static TComponent CloneComponent<TComponent>(this TComponent source) where TComponent : Component, new()
{
TComponent clone = new TComponent(); //Create the new instance
//Clone the source code here
return clone;
}
在我的项目中,我的方法实际上有克隆代码,但由于它没有任何问题要处理,我将其删除。
对于我的组件类的一些解释,我有一个名为Component
的根类,但后来我创建了派生自Component
的类,我试图克隆它。
例如,我可能有一个名为&#34; PlayerController&#34;:
的组件class PlayerController: Component
所以如果我想克隆一个PlayerController
我输入那个作为类型参数; TComponent
应为PlayerController
类型。
所以,让我们说我试图克隆一个PlayerController
组件。
如果我调试源组件的名称,即组件中的GetType().ToString()
:
Debug.WriteLine(source.name);
我得到输出&#34; PlayerController&#34;。
这意味着TComponent
的类型为PlayerController
,对吧?
但是,如果我调试克隆的名称,TComponent
的新实例,我得到输出&#34;组件&#34;。这意味着由于某种原因,我的新TComponent
实例已转换为根类型??
有趣的是,当我在控制台应用程序中重新创建此内容时,我不会收到此错误...
修改:
测试来源:
static class Program
{
static void Main(string[] args)
{
PlayerController e = new PlayerController();
PlayerController eClone = Extensions.CloneComponent(e);
Console.WriteLine(e.name);
Console.WriteLine(eClone.name);
}
}
public class Component
{
}
public class PlayerController : Component
{
}
public static class Extensions
{
public static TComponent CloneComponent<TComponent>(this TComponent source) where TComponent : Component, new()
{
var clone = new TComponent();
var srcProperties = System.ComponentModel.TypeDescriptor.GetProperties(typeof(TComponent)).Cast<System.ComponentModel.PropertyDescriptor>();
foreach (var srcProperty in srcProperties)
{
srcProperty.SetValue(clone, srcProperty.GetValue(source));
}
return clone;
}
}
控制台输出的内容是:
的PlayerController
的PlayerController
这意味着TComponent实际上是源的类型。
当我做同样的事情时,我怎么没有在我的项目中得到相同的结果?
编辑2 :
source参数取自Components列表,因此当用作参数时,它显然会转换为root类型...当我调试它之前,它正确地键入了它给我正确的类型。我想我不得不再提出一个关于如何绕过这个问题的问题。
答案 0 :(得分:0)
我不确定你的实际问题是什么。你的代码似乎很好,似乎给你你想要的PlayerController。如果我运行下面的代码,我会得到:
Source: Tester.PlayerComponent, clone: Tester.PlayerComponent
来源:
namespace Tester
{
class Program
{
static void Main(string[] args)
{
var item = new PlayerComponent() {Name = "PlayerOne"};
var item2 = item.CloneComponent();
Console.ReadLine();
}
}
public static class Extensions
{
public static TComponent CloneComponent<TComponent>(this TComponent source) where TComponent : Component, new()
{
TComponent clone = new TComponent(); //Create the new instance
//Clone the source code here
Console.WriteLine($"Source: {source.GetType()}, clone: {clone.GetType()}");
return clone;
}
}
public class Component
{
}
public class PlayerComponent : Component
{
public string Name { get; set; } = "Test";
}
}
答案 1 :(得分:0)
我认为你缺少的是C#中的泛型类型在编译时被实例化。这意味着TComponent
的类型是根据您传入source
的{{1}}的(静态编译时)类型设置的。编译器无法看到CloneCompenent
中包含的实际对象可能属于另一种类型的事实。
由于您无法知道对象的动态类型,因此必须使用继承并将克隆操作委派给实际类型。在Component类中:
source
在PlayerComponent类中:
public static Component CloneComponent(this Component source) => return source.CloneMyself();