创建新的泛型类型实例转换为根类型?
我目前正在尝试克隆我称为“Component”的XNA项目中的自定义类型,让它看起来像这样。创建新的泛型类型实例转换为根类型?
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
派生的类,我试图克隆。
因此,举例来说,我可能已经调用组件“的PlayerController”:
class PlayerController: Component
所以,如果我想克隆一个PlayerController
I输入,作为类型参数; TComponent
应该是PlayerController
类型。我们假设我试图克隆PlayerController
组件。
如果我调试的源组件,它是在组件GetType().ToString()
名称:
Debug.WriteLine(source.name);
我得到的输出“的PlayerController”。
所以这意味着TComponent
是PlayerController
类型,对不对?
但是,如果我调试克隆的名称,TComponent
的新实例,我会得到输出“组件”。这意味着由于某种原因,我的新实例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
Play erController
这意味着TComponent实际上是源的类型。
当我做完完全相同的事情时,我在项目中没有得到相同的结果?
编辑2:
源参数是从组件列表拍摄,因此显然作为参数使用时将它转换成根型......当我调试它是正确键入它给我的前正确的类型。我想我只能提出另一个关于如何绕过这个问题的问题。
我不太确定你的实际问题是什么。你的代码看起来很好,似乎给你像你想要的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";
}
}
我的代码看起来不错,但它并不像我想要的那样给我PlayerController。当我创建一个新的TComponent'TComponent clone = new TComponent();''clone'的类型总是Component,即使源的类型不是。 –
上面的示例代码中是否存在缺失的内容? item2被视为类型PlayerComponent。 – jeremywho
没有什么缺失,当我在控制台应用程序中尝试此操作时,我还在项目2上获得PlayerComponent作为类型。但在我的项目中,TComponent始终是根类型Component,当我创建它的一个新实例'TComponent clone = new TComponent();' –
我认为你缺少的是,在C#泛型类型是在编译时实例化。这意味着TComponent
的类型是基于source
的(静态编译时)类型设置的,您可以将其输入CloneCompenent
。编译器无法看到source
中包含的实际对象可能是另一种类型的事实。
由于无法知道对象的动态类型,因此必须使用继承并将克隆操作委托给实际类型。在组件类:
public static Component CloneComponent(this Component source) => return source.CloneMyself();
在PlayerComponent类:
public Component CloneMyself() {
var clone = new PlayerComponent(this); // special constructor takes self type
return (Component) clone;
}
但是,这不仅仅返回基类型“Component”的对象吗?我看到这种演变成XY的问题,我真的没有想到,对不起...... –
不,它会返回任何类型的对象。它们将被存储在一个类型为'Component'的变量中,这可能是由于继承造成的,但实际的(运行时)类型将来自克隆对象。您可能想了解更多有关继承的内容。 – NetMage
看看我的编辑。 –
您能得到什么,如果你调试'typeof运算(TComponent)的ToString()'在功能或放在一个变量来检查像'var x = new TComponent()'? – NetMage
@NetMage看起来像我得到的根类型... –
所以现在你知道'TComponent'的类型。 – NetMage