通过反射在类上调用多个泛型接口方法

4

警告:虽然接受的答案是正确的,但对于任何试图实现此功能的人,请查看@CodesInChaos的评论。这是我自己的一个坏主意。


我有一个通用接口和一个实现该接口的类,可以实现'n'次:

interface IA<T>
{
    T Foo();
}

class Baz1 { }
class Baz2 { }

class Bar : IA<Baz1>, IA<Baz2>
{
    Baz1 Foo() { return new Baz1(); }
    Baz2 Foo() { return new Baz2(); }
}

如何使用反射在 Bar 实例上调用 Foo 方法?

我已经有以下代码来获取接口定义和泛型类型参数:

class Frobber
{
    void Frob(object frobbee)
    {
        var interfaces = frobbee.GetType()
            .GetInterfaces()
            .Where(i => i.IsGenericType &&
                i.GetGenericTypeDefinition() == typeof(IA<>).GetGenericTypeDefinition());
    }
}

在我的具体情况中,我有一个 Bar 类实现了 IObservable<Baz1>IObservable<Baz2> 等等,同时也实现了 IObserver<Baz1>IObserver<Baz2> 等等,而不是 IA<T>。但我不想混淆讨论。也许这很相关? - Lars Kemmann
1
你确定你想在这里使用继承而不是组合吗? - CodesInChaos
1
那我直说吧。你不应该这样做。IObservable<out T>是协变的。因此,如果你为不同的T实现它,返回不同的序列,你将无法获得正确的IObservable<object>实现。 - CodesInChaos
我理解你的观点。:) 谢谢。 - Lars Kemmann
1
关于实现两个不同版本的 IEnumerable<T> 的类似问题:1)一个类上有多个 IEnumerable<T> 接口 - 如何处理非泛型方法? 2)在 C# 中实现多个 IEnumerables - CodesInChaos
显示剩余3条评论
1个回答

4

定义:

interface IA<T>
{
    T Foo();
}

class Baz1 { }
class Baz2 { }

class Bar : IA<Baz1>, IA<Baz2>
{
    Baz2 IA<Baz2>.Foo()
    {
        return new Baz2(); 
    }

    Baz1 IA<Baz1>.Foo()
    {
        return new Baz1(); 
    }
}

代码:

    Bar b = new Bar();
    var methods = typeof(Bar).GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IA<>)).Select(i => i.GetMethod("Foo"));
    foreach(var method in methods)
    {
        var invoked = method.Invoke(b, null); // or add params instead of null when needed
    }

1
谢谢,我忘记了必须要明确实现。 - Lars Kemmann
请注意,methods 中只应该有一个或零个元素,因此可能需要用更合适的 FirstOrDefault + 检查来替换 Select - SimpleVar
@YoryeNathan,你可以获取多个MethodInfo对象,而且你会需要它们。你不能使用FirstOrDefault,因为这样会打乱目的。 - Stavros Zotalis
同一个类中可以使用多个实现显式接口方法吗?如何实现? - SimpleVar
如果这个方法被重载了,你是正确的。但是如果这个方法只有一个签名的话,我会使用FirstOrDefault - SimpleVar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接