2017-07-31 5 views
1

私は現在、 "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入力のクローンを作成したい場合は、その型の引数として; TComponentPlayerControllerである必要があります。

したがって、PlayerControllerコンポーネントをクローンするとします。

私はコンポーネントでGetType().ToString()あるソース・コンポーネントの名前デバッグする場合:

Debug.WriteLine(source.name); 

を私は出力「PlayerController」を取得します。

つまり、TComponentPlayerControllerです。右ですか?

しかし、クローンの名前をデバッグすると、新しいインスタンス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
ソースパラメータは、コンポーネントのリストから取られ、そして引数として使用した場合、私はそれは私与えます前に、それが正しい型のデバッグするときので、どうやらそれは...ルート・タイプに変換され、正しいタイプ。私はちょうどこれを回避する方法について別の質問をしなければならないと思う。

+0

あなたは何を得るのですか'var x = new TComponent()'のように? – NetMage

+0

@NetMageルートタイプを取得したようです... –

+0

これで、 'TComponent'の型が分かりました。 – NetMage

答えて

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"; 
    } 
} 
+0

私のコードはうまく見えますが、私が望むように私にPlayerControllerを与えていません。私が新しいTComponentを作成すると、TComponent clone = new TComponent();ソースの型がComponentではないにもかかわらず、 'clone'の型は常にComponentになります。 –

+0

上記のサンプルコードに何か不足していますか? item2はPlayerComponent型と見なされます。 – jeremywho

+0

コンソールアプリケーションでこれを試したときに、タイプ2としてPlayerComponentを取得します。しかし、私のプロジェクトでは、TComponentは常に新しいタイプのインスタンスを作成するときに、ルートタイプのComponentです。 'TComponent clone = new TComponent();' –

0

を私はあなたが欠けているものだと思うC#でジェネリック型はコンパイル時にインスタンス化されていることです。つまり、タイプTComponentは、CloneCompenentに渡されたsourceの(静的コンパイル時)タイプに基づいて設定されます。そのsourceに含まれる実際のオブジェクトが別のタイプである可能性があるという事実は、コンパイラには見えません。

オブジェクトの動的型を知ることができないため、継承を使用して、クローン操作を実際の型に委譲する必要があります。 PlayerComponentクラスで

public static Component CloneComponent(this Component source) => return source.CloneMyself(); 

::Componentクラスでは、あなたが `typeof演算(TComponentの).ToString()`関数または確認するために、変数に入れてデバッグする場合

public Component CloneMyself() { 
    var clone = new PlayerComponent(this); // special constructor takes self type 
    return (Component) clone; 
} 
+0

これは、基本タイプのComponentオブジェクトのみを返しますか?私はこの種のXY問題に進化しました。私は本当にそれを期待していませんでした。ごめんなさい... –

+0

いいえ、呼び出されたタイプのオブジェクトを返します。継承のために可能な 'Component'型の変数に格納されますが、実際の(実行時)型はクローンオブジェクトからのものになります。継承についてもっと読むことができます。 – NetMage

+0

私の編集を見てください。 –

関連する問題