访问泛型参数的泛型参数?

Accessing the generic parameter of generic parameter?

我很难解决 C# 中的问题。

在我正在做的项目中,有一些consumable 类存储信息,还有consumer 类使用那些消耗品类.

我用更简单的方式复制了这个东西:

using System;
using System.Collections.Generic;

interface IBase
{
    int x {get;}
}

class BaseClass : IBase
{
    public int x {get; set;}
}

interface IDerived : IBase
{
    int y {get;}
}

class DerivedClass : BaseClass, IDerived
{
    public int y {get; set;}
}

interface IConsumer<in T> where T: class, IBase
{
    void Feed(T arg);
}

class BaseConsumer : IConsumer<IBase>
{
    public void Feed(IBase arg)
    {
        Console.WriteLine(arg.x);
    }
}

class DerivedConsumer : IConsumer<IDerived>
{
    public void Feed(IDerived arg)
    {
        Console.WriteLine(arg.y);       
    }
}

public class Program
{
    public static void Main()
    {
        List<IConsumer<IDerived>> consumers = new List<IConsumer<IDerived>>();
        consumers.Add(new BaseConsumer());
        consumers.Add(new DerivedConsumer());

        DerivedClass d = new DerivedClass() { x = 3, y = 5};

        foreach (IConsumer<IDerived> consumer in consumers)
            consumer.Feed(d);
    }
}

这完全没问题。但是,我也希望有一些 middle 消费者,它在其构造函数(或其他方法)中采用另一个 consumer 对象,它将 Feed 调用重定向到对象。例如:

class MiddleConsumer<T> : IConsumer<T> where T : class, IBase
{
    private IConsumer<T> _consumer;
    public MiddleConsumer(IConsumer<T> consumer)
    {
        _consumer = consumer;
    }

    public void Feed(T arg)
    {
        _consumer.Feed(arg);
    }
}

我会这样使用它:

consumers.Add(new MiddleConsumer<IBase>(new BaseConsumer());
consumers.Add(new MiddleConsumer<IDerived>(new DerivedConsumer());

但我会将 MiddleConsumer 与其他具体 Consumer 类 一起使用,例如 BaseConsumerDerivedConsumer。因此我不必明确指定 T 参数,它可以从实际的 Consumers 类型中获取它。让我澄清一下。我想要这样的东西:(注意这不是有效的 C# 代码)

class MiddleConsumer<IConsumer<T>> : IConsumer<T>
{
    private IConsumer<T> _consumer;
    public MiddleConsumer(IConsumer<T> consumer)
    {
        _consumer = consumer;
    }

    public void Feed(IDerived arg)
    {
        _consumer.Feed(arg);
    }
}

但是,正如预期的那样,由于具有那个奇怪的通用参数,这不起作用。

我希望能够使用我不知道其基本类型的 Consumer 创建 MiddleConsumer 对象。我的意思是,我希望能够做到这一点:

consumers.Add(new MiddleConsumer<BaseConsumer>(new BaseConsumer());
consumers.Add(new MiddleConsumer<DerivedConsumer>(new DerivedConsumer());

我不想在每次想将它与 MiddleConsumer 一起使用时检查 - 例如 - BaseConsumer 的基类型,因为编译器可以在我使用时查看它ConsumerMiddleConsumer。请注意,可能有许多不同的 Consumer 类.

我的问题是:有没有办法让 C# 编译器从其泛型参数推断出 MiddleConsumer 的可使用类型?

感谢您的帮助!

C# 不支持对构造函数的类型推断,但您可以做的是通过静态方法委托对构造函数的调用:

public static class MiddleConsumer
{
    public static MiddleConsumer<T> Create<T>( IConsumer<T> consumer ) where T : class, IBase
    {
        return new MiddleConsumer<T>( consumer );
    }
}

现在您根本不需要指定通用参数:

consumers.Add(MiddleConsumer.Create(new BaseConsumer());