2

我发现自己处于这样一种情况,即我在基类上有一个方法,该方法调用了一个将自身作为参数传递的泛型方法(通过this)。在泛型方法中,类型始终是基类型,即使我从派生类调用该方法也是如此。

我需要泛型方法来知道它是派生类型而不是基类型。

我无法更改通用方法,因为它来自第三方应用程序(http://razorengine.codeplex.com/ -Razor.Parse方法)。

我发现,如果我将该方法定义为仅限于从我的基类继承的类型的通用扩展方法,那么调用它就可以工作,但是为此目的使用扩展方法似乎很混乱(尽管如果这是正确的用法,我会很高兴听到)。我想知道是否有一些技巧可以在调用之前将“this”转换为派生对象的类型(可能仍然使用泛型)。

我在下面包含了一个应该是自包含的简化程序(为了个人方便,我在 LINQPad 中运行它)。本质上,我想要一个A在调用实例时定义的方法,B将调用Test.WhatType并输出“B”。

我希望这是有道理的。

void Main()
{
    var bar = new B();
    bar.myGetType();
    bar.ExtGetType();
}

class A
{
    public virtual void myGetType()
    {
        Test.WhatType(this);
        this.ExtGetType();
    }
}

class B : A {}

static class ext
{
    public static void ExtGetType<T>(this T obj) where T : A
    {
        Test.WhatType(obj);
    }
}

class Test
{
    public static void WhatType<T>(T obj)
    {
        Console.WriteLine(typeof(T).Name);
    }
}

编辑:将方法名称更改为,A.myGetType()因为我什至没有注意到我意外重载。

注意运行此代码输出:

A
A
B
4

3 回答 3

3

你需要使用obj.GetType(). T在编译时绑定,而不是在运行时绑定,因此typeof(T)返回T.

于 2012-05-02T12:59:50.437 回答
2

如果我理解正确,您的问题是A.GetType()绑定到WhatType<A>它所知道的所有内容。

所以你必须让类A知道派生类。

您可以使用自引用泛型类型来做到这一点。就像是:

class A<T> where T : A<T>
{
    public virtual void GetType()
    {
        Test.WhatType<T>( (T) this );
    }
}

class B : A<B> { }

然后:

new B().GetType();

将绑定到WhatType<B>,因此将输出B

于 2012-05-02T13:12:02.493 回答
-1

此方法返回静态类型 (T) 的类型。它应该被实施为

public static void WhatType<T>(T obj) 
{ 
    Console.WriteLine(obj.GetType().Name); 
} 

编辑:我刚刚意识到你想要的是以通用方法的 T 改变的方式操作 A 。您可以通过反射或添加基于 A 的子类型的 switch 语句并将其显式转换为 B(或任何类)来执行此操作。当然,这些解决方案都不好,因为 A 会依赖于它的子类和反射显然是 sux。另一种选择是覆盖每个子类中的 GetType() 方法,从而将责任转移到子类。

于 2012-05-02T12:57:37.013 回答