2012-03-12 8 views
2

私がまとめているオブジェクトは、オブジェクトが同じタイプの別のオブジェクトによって変換できるものとして自分自身を公開できるようにすることです。マージの行に沿って考えると、操作は一般的ではなく、単純にすべてのプロパティを取得して所定の操作を実行するためにリフレクションを使用することはできません。そこで、私はそれをTransformableとして公開するオブジェクトとして実装し、変換を実行する方法を知っているオブジェクト(入れ替えることができる)をオブジェクトにアタッチすることに決めました。私がこれまで持ってコンパイルコードは次のとおりです。あなたが見ることができるようにC#このキーワードを使用するときのジェネリック型

public interface ITransformer<TType> where TType : class 
{ 
    void Transform(TType source, TType destination); 
} 

public interface ITransformable<TType> where TType : class 
{ 
    bool Locked { get; set; } 
    ITransformer<TType> Transformer { get; set; } 

    void TransformFrom(TType source); 
} 

public class MyTransformer : ITransformer<MyTransformable> 
{ 
    public void Transform(MyTransformable source, MyTransformable destination) 
    { 
     // Perform some logic for the transform 
    } 
} 

public class MyTransformable : ITransformable<MyTransformable> 
{ 
    public bool Locked { get; set; } 
    public ITransformer<MyTransformable> Transformer { get; set; } 

    public string Value1 { get; set; } 
    public uint Value2 { get; set; } 
    public bool Value3 { get; set; } 

    public void TransformFrom(MyTransformable source) 
    { 
     Transformer.Transform(source, this); 
    } 
} 

、タイプMyTransformableは、いくつかのデータ(値1 - VALUE3)が含まれてだけでなく、ロック状態とトランスオブジェクトが知っているだろうこのアイテムの変換をどのように行うか(MyTransformerタイプで動作可能なトランスフォーマーのみが許可されたジェネリック)。

私の問題は、私はタイプ変換可能のすべての新しいオブジェクトが

public void TransformFrom(MyTransformable source) 
{ 
    Transformer.Transform(source, this); 
} 

へのコールを繰り返す必要はしたくないということですので、私は

MyTransformableオブジェクトの変更を追加することができます期待していました
public abstract class Transformable<TType> : ITransformable<TType> where TType : class 
{ 
    public bool Locked { get; set; } 
    public ITransformer<TType> Transformer { get; set; } 

    public void TransformFrom(TType source) 
    { 
     Transformer.Transform(source, this); // ERROR! this is type Transformable<TType> not TType 
    } 
} 

public class MyTransformable : Transformable<MyTransformable> 
{ 

} 

もちろん、これは私が強調しているエラーのためにコンパイルされません。私はラインのどこかでポイントを逃したように感じる。誰かがこれについて正しい方向に私を指すことができますか?

+0

これがうまくいくと思いますか?「変形可能な」? 'this'が' int'型になることはありません。 –

+0

可逆変換を行っている場合は、代わりにクラスのキャスト演算子を実装することができます。 http://msdn.microsoft.com/en-us/library/z5z9kes2(v=vs.100).aspx http://msdn.microsoft.com/en-us/library/xhbhezf4(v=vs.100) 。aspx – JamieSee

+0

「ITransformer 」と「ITransformable 」にいくつかの一般的な制約を適用する必要があります。 –

答えて

1

が追加され最終的な実数TTypeの実装(または単にthis)を公開するための派生型のフックこれは、抽象プロパティを使用して行うのが最適です。

public abstract class Transformable<TType> : ITransformable<TType> 
{ 
    public bool Locked { get; set; } 
    public ITransformer<TType> Transformer { get; set; } 

    protected abstract TType Value { get; } 

    public void TransformFrom(TType source) 
    { 
     Transformer.Transform(source, Value); 
    } 
} 

public class MyOtherTransformable : Transformable<MyTransformable> 
{ 
    protected override MyTransformable Value 
    { 
     get { return this; } 
    } 
} 
+0

治療を受けてください。最後のサブクラスが何かをオーバーライドする必要がないことが大好きでしたが、「動的」キャストを使用することによるペナルティは悪化しています。ヒントをありがとう! –

0

それはあなたがおそらく慣れているとも、あなたが何をしようとしての目的を倒すが、これはコンパイルしているよりも多くの鋳造になります:あなたがする必要がどのような

public interface ITransformable { } 

public interface ITransformer<TType> 
    where TType: ITransformable 
{ 
    void Transform(ITransformable source, ITransformable destination); 
} 

public interface ITransformable<TType> : ITransformable 
    where TType: ITransformable 
{ 
    bool Locked { get; set; } 
    ITransformer<TType> Transformer { get; set; } 

    void TransformFrom(TType source); 
} 

public class MyTransformer : ITransformer<MyTransformable> 
{ 
    public void Transform(ITransformable source, ITransformable destination) 
    { 
     if (source.GetType() != destination.GetType()) 
      throw new InvalidOperationException(); 

     // Perform some logic for the transform 
    } 
} 

public abstract class Transformable<TType> : ITransformable<TType> where TType: ITransformable 
{ 
    public bool Locked { get; set; } 
    public ITransformer<TType> Transformer { get; set; } 

    public void TransformFrom(TType source) 
    { 
     Transformer.Transform(source, this); 
    } 
} 

public class MyTransformable : Transformable<MyTransformable> 
{ 

} 
+1

TransformerのTransformメソッドでは、2つのITransformableパラメータが同じ実際の型であることを確認する必要があります。 – KeithS

+0

@KeithS - 良いキャッチ。 –

1

は、.NET 4を使用している場合、あなたはdynamicにキャストを使用することができます。

public void TransformFrom(TType source) 
{ 
    Transformer.Transform(source, (dynamic)this); 
} 

これは、CLRは、実数型(に基づいて、実行時にパラメータの型マッチングを行うことができますコンパイル時のエラーを防止します。実行時に、CLRは簡単にsourcethisが同じタイプであると判断して呼び出しを実行します。

それはあなたの問題を解決します。欠点は、dynamicの使用が本質的に反射的なプロセスであり、最初に遅くなり、2番目にランタイム例外を引き起こすバグを隠すことができるということです。

関連する問題