C# 转换继承的通用接口 [英] C# casting an inherited Generic interface

查看:20
本文介绍了C# 转换继承的通用接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在投射我想出的界面时遇到了一些麻烦.它是 C# Windows 窗体的 MVP 设计.我有一个在表单类上实现的 IView 类.还有一个 IPresenter,我将其派生为各种特定的 Presenter.每个 Presenter 将根据角色不同地管理 IView,例如打开对话框以使用 AddPresenter 输入一组新数据,而不是使用 EditPresenter 编辑现有数据,后者会将数据预加载到表单上.每一个都继承自 IPPresenter.我想这样使用代码:

I'm having some trouble getting my head around casting an interface I've come up with. It's an MVP design for C# Windows Forms. I have an IView class which I implement on my form classes. There's also an IPresenter which I derive into various specific Presenters. Each Presenter will manage the IView differently depending on the role, for example opening the dialog to enter a new set of data with an AddPresenter as opposed to editing existing data with an EditPresenter which would preload data onto the form. Each of these inherit from IPresenter. I want to use the code as such:

AddPresenter<ConcreteView> pres = new AddPresenter<ConcreteView>();

我基本上有这个工作,但这些演示者和他们管理的视图被捆绑到插件中,这些插件在运行后加载,这意味着我需要一个管理器类,它作为插件接口使用模式"参数.此模式参数用于工厂方法以创建添加或编辑演示者,但由于稍后调用显示对话框,因此我需要通过 IPresenter 接口进行调用,如下所示:

I basically have this working but these presenters and the views they manage are bundled into plugins which are loaded post runtime which means I need a Manager class which acts as the plugin interface take a "mode" parameter. This mode parameter is use for a factory method to create either the Add or Edit Presenter, but because the call to show the dialog is made later on then I need to make the call via the IPresenter interface like so:

private IPresenter<IView> pres;
public ShowTheForm()
{
    pres.ShowDialog();
}

现在我在将我的 AddPresenter 的具体实例化到pres"成员时遇到了问题.这是我所拥有的简化版本:

Now I'm having issues when it comes to casing my concrete instantiation of an AddPresenter say, to the 'pres' member. Here's a cut down simplified version of what I have:

interface IView
{
    void ViewBlah();
}

interface IPresenter<V> where V : IView
{
    void PresBlah();
}

class CView : IView
{
    public void ViewBlah()
    {        
    }
}

class CPresenter<T> : IPresenter<T> where T : IView
{
    public void PresBlah()
    {
    }
}

private void button3_Click(object sender, EventArgs e)
{
    CPresenter<CView> cpres = new CPresenter<CView>();
    IPresenter<IView> ipres = (IPresenter<IView>)cpres;
}

这是错误:

Unable to cast object of type 'CPresenter`1[MvpApp1.MainForm+CView]' to type 'IPresenter`1[MvpApp1.MainForm+IView]'.

Presenter 和 Generic 类型规范都来自我可以告诉接口的 ARE 子类的内容,所以我不明白为什么它不会强制转换.

Both the Presenter and the Generic type specification from what I can tell ARE subclasses of the interfaces so I can't understand why it won't cast.

有什么想法吗?

史蒂夫

推荐答案

问题是泛型类型参数.如果您使接口参数协变,则转换将起作用.

The problem is the generic type parameter. If you make the interface parameter covariant then the cast will work.

这是通过添加 out 关键字来实现的,如下所示:

This is accomplished by adding the out keyword, like so:

interface IPresenter<out V> where V : IView
{
    void PresBlah();

}

您可以通过以下 MSDN 文章了解有关其工作原理的更多信息:协方差和泛型中的逆变.具有协变类型参数的通用接口部分特别适用于您的问题.

You can learn more about how this works with the following MSDN article: Covariance and Contravariance in Generics. The section Generic Interfaces with Covariant Type Parameters specifically applies to your question.

更新:请务必查看@phoog 和我之间的评论.如果您的实际代码接受 V 作为输入,您将无法使其协变.引用的文章和@phoog 的回答更详细地解释了这种情况.

Update: Make sure you check the comments between @phoog and me. If your actual code accepts a V as an input, you will be unable to make it covariant. The referenced article and @phoog's answer explains this case in further detail.

这篇关于C# 转换继承的通用接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆