【问题标题】:Invoking generic method/delegate from a non-generic base class从非泛型基类调用泛型方法/委托
【发布时间】:2016-01-12 18:10:59
【问题描述】:

我觉得我在这里没有从正确的角度看待这个问题,我只是没有考虑其他解决方案。

假设这个泛型类;

public abstract class Port<T>
{
    public delegate T PullDelegate();

    private PullDelegate pull;

    public Port(PullDelegate pull)
    {
        this.pull = pull;
    }

    public T Pull()
    {
        return pull();
    }
}

它用于在图形节点编辑器中定义“端口”。端口可以​​将对象/值从一个节点传输到另一个节点,但它们也需要是“类型安全的”,这意味着我不能将任何端口插入到另一个错误类型的端口(至少在没有一些转换的情况下不会)。

节点“拥有”一个端口并给它一个委托给它的一个方法,所以当另一个节点“拉”一个值时,端口简单地调用它并返回正确的值。

当我尝试从非泛型集合中调用 Pull() 时,我的问题就开始了。显然,我可以创建一个非泛型基方法,但是 Pull 无法返回 T,它需要返回 object

此外,每个节点都有其端口的集合访问器,因此其他项目可以获取它们。该集合必须是非泛型的,因为一个节点可以有许多类型的端口。

    public abstract Port[] Inputs { get; }
    public abstract Port[] Outputs { get; }
    public abstract Port[] Entries { get; }
    public abstract Port[] Exits { get; }

当非泛型类型开始发挥作用时,所有泛型都变得不可访问。如果只有Port&lt;&gt;[] 会是一件事。

我觉得我错过了什么......

【问题讨论】:

  • 您可以创建一个IPort&lt;out T&gt; { T Pull(); },然后创建一个IEnumerable&lt;Port&lt;object&gt;&gt;
  • 那么你的对象都将实现一个接口,这样你就可以确定它至少会是实现该接口的对象,这会改变你的情况吗?所以你可以避免使用对象,而是使用 IMyObject 之类的东西。
  • PortPort&lt;T&gt; 的基类吗?您究竟想如何使用非泛型集合?
  • 前段时间,我用Visitor Pattern解决了这样一个问题。看看这是否有帮助,或者展示您的用例,我会尝试根据您的要求调整解决方案。 Here's another sample of same pattern
  • @SriramSakthivel:我还不确定。我的第一个想法是做Port&lt;T&gt; : Port。现在,我正在通过IPort&lt;object&gt; 尝试李的建议。

标签: c# generics


【解决方案1】:

使用显式实现使Port&lt;T&gt; 实现非泛型接口IPort。通过这种方式,它对 API 隐藏,但仍然允许您调用泛型类中的方法。

public interface IPort
{
    object SomeAction(object data);
}

public class Port<T> : IPort
{
    //[.. all other methods ..]


    object IPort.SomeAction(object data)
    {
        var typedData = (T)data;
        //invoke our typed version.
        return SomeAction(data);
    }

    public T SomeAction(T data)
    {
         // ...
    }
}

【讨论】:

  • 如果我的问题只是传递一些东西给它,我不会为泛型而烦恼。我的问题是我从中得到了一些东西。假设您的 SomeAction 返回 T
  • @LightStriker:从 IPort.SomeAction 返回对象和从 IPort.SomeAction 返回 T 怎么样(IPort 实现 IPort)?我认为这就是他们在 IEnumerable/IEnumerable 中所做的。
  • @jgauffin 实际上,我使用类似于在 List 中实现 IEnumerable 的 IPort/IPort 实现了 Devstruck 提出的建议。有用。我刚刚注意到,我现在使用通用 IPort 的方式可能实际上并不需要它。我可能会保留它以防万一。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-04
  • 1970-01-01
  • 1970-01-01
  • 2021-02-16
相关资源
最近更新 更多