使用此关键字时的C#Generics类型

时间:2012-03-12 19:59:05

标签: c# generics this

我放在一起的对象是允许一个对象将自己暴露为可由另一个相同类型的对象转换的东西。按照合并的方式思考,但操作不是通用的/直接的,因此您可以使用反射来简单地获取所有属性并执行一些预定的操作。因此,我决定尝试将其实现为将自己暴露为 Transformable 的对象,并将一个知道如何执行转换的对象(可以互换)附加到它们。我到目前为止可编辑的代码是:

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 类型包含一些数据(Value1 - Value3)以及 Locked 状态和 Transformer 对象将知道如何对此项执行转换(通用,确保只允许变换器能够作用于 MyTransformer 类型)。

我的问题是我不希望 Transformable 类型的所有新对象都必须重复调用

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>
{

}

但是由于我突出显示的错误,当然不会编译。我觉得我已经错过了沿线的某个地方。有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分: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; }
    }
}

答案 1 :(得分:1)

如果您使用的是.NET 4,则可以使用强制转换为dynamic

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

这允许CLR在运行时根据执行时对象的实际类型(封闭泛型)执行参数类型匹配,从而防止编译时错误。在运行时,CLR可以轻松地告诉sourcethis是相同的类型,并将执行调用。

好处是它解决了你的问题。缺点是使用dynamic是一个固有的反思过程,第一个慢,第二个可以隐藏会导致运行时异常的错误。

答案 2 :(得分: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>
{

}