2012-03-12 47 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是一个固有的反射过程,它首先比较慢,然后可以隐藏导致运行时异常的错误。