2012-03-12 58 views
2

我放在一起的對象是允許對象將自己公開爲可以由相同類型的另一個對象進行轉換的對象。按照合併的思路思考,但操作不是通用/直接的,這樣您就可以使用反射來簡單地獲取所有屬性並執行一些預定義的操作。因此,我決定嘗試將它實現爲可展示爲可變形的對象,並將它們附加到知道如何執行轉換(可以互換)的對象。該編譯代碼我至今是: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 - 值3)以及一個鎖定狀態和變壓器對象就知道如何執行該項目的變換(泛型確保只有變壓器能夠在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'類型。 – 2012-03-12 20:07:30

+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 2012-03-12 20:09:18

+0

爲了實現你的目標,你需要對'ITransformer '和'ITransformable '執行一些通用約束。 – 2012-03-12 20:09:51

回答

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

作品。本來希望不要求最終的子類必須重寫任何東西,但使用「動態」類型的懲罰似乎更糟糕。謝謝你的提示! – 2012-03-13 07:08:50

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方法中,您需要檢查兩個ITransformable參數是否是相同的實際類型。 – KeithS 2012-03-12 20:34:41

+0

@KeithS - 好的。 – 2012-03-12 20:42:09

1

如果您使用.NET 4,你可以使用強制轉換爲dynamic

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

這使得CLR根據實際類型在運行時做的參數類型匹配(關閉通用)在執行時,防止編譯時錯誤。在運行時,CLR可以很容易地知道sourcethis是相同的類型並且將執行呼叫。

好處是它解決了您的問題。缺點是使用dynamic是一個固有的反射過程,它首先比較慢,然後可以隱藏導致運行時異常的錯誤。