派生类型的调用扩展方法

时间:2014-10-29 12:39:10

标签: c#

简介

我需要在通用抽象类上创建一个扩展方法,但是只暴露基本的非泛型抽象类。永远不会有一个直接从Abstract继承的具体类。

public abstract class Abstract { }

public abstract class Abstract<T> : Abstract { }

public class Concrete : Abstract<string> { }

方法

public static Abstract GetConcrete()
{
    return new Concrete();
}

public static class Extensions
{
    public static void Extension<T>(this Abstract<T> a)
    {
        Console.WriteLine("Generic");
    }
}

用法

Abstract a = GetConcrete();
a.Extension();

错误

以上结果是编译时错误:

  

'Abstract'不包含'Extension'的定义,并且没有扩展方法'Extension'接受类型'Abstract'的第一个参数可以找到

我认为在Abstract上添加了扩展名,但这不允许我转换为更具体的扩展名:

public static void Extension(this Abstract a)
{
    Console.WriteLine("Base");
    Abstract<?> cast = MagiclyCastToGeneric(a);
    Extensions.Extension(cast);
}

2 个答案:

答案 0 :(得分:1)

一种方法是使用dynamic

的“魔力”
public static void Extension(this Abstract a)
{
    Console.WriteLine("Base");

    dynamic d = a;

    Extensions.Extension(d);
}

这导致重载决策在运行时而不是编译时完成 - DLR将选择要选择的最具体的重载版本,即Extension(this Abstract<T>)

请注意,如果有一个具体类型直接继承Abstract,那么上面会导致StackOverflowException

答案 1 :(得分:0)

如果你不能像在dav_i的答案中那样使用DLR / dynamic(即你在.Net2.0上),你可以手动以类似的方式做到这一点。伪代码:

public static void Extension(this Abstract a)
{
    var actualType = a.GetType();
    var interestingBaseType = ...search basetypes of actualType for Abstract<T>
    var theTypeParameter = interestingBaseType.GetGenericArguments()[0];

    var genericMethodDef = typeof(Extensions).GetMethod("Extension");
    var concreteMethod = genericMethodDef.MakeGenericMethod(theTypeParameter);

    concreteMethod.Invoke(a, ....);
}