C# 在使用类型泛型时,如何正确地将类强制转换为抽象类?

C# 在使用类型泛型时,如何正确地将类强制转换为抽象类?,c#,reflection,.net-3.5,C#,Reflection,.net 3.5,我有以下课程 public abstract class BaseViewPresenter { } public abstract class BaseView<T> : UserControl where T : BaseViewPresenter { } public class LoginPresenter : BaseViewPresenter { } public partial class LoginView : BaseView<LoginPresen

我有以下课程

public abstract class BaseViewPresenter { }
public abstract class BaseView<T> : UserControl
    where T : BaseViewPresenter { }

public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter> {  }
Activator.CreateInstance(viewType)
正确解析为my
LoginView
的新实例,但是
控件as BaseView
无法正确执行强制转换,因此返回
null

是否有一种方法可以在不使用特定类型泛型的情况下将
控件
正确转换为
BaseView

由于
LoginView
继承自
BaseView
LoginPresenter
继承自
BaseViewPresenter
,我假设有一种方法可以将
LoginView
转换为
BaseView


我一直在使用.Net 3.5,您希望将该类型视为与泛型参数相关的协变类型。类永远不可能是协变的;您需要使用一个接口而不是(或附加)一个抽象类,以使它相对于
T
协变。您还需要使用C#4.0。

您希望将类型视为与泛型参数相关的协变类型。类永远不可能是协变的;您需要使用一个接口而不是(或附加)一个抽象类,以使它相对于
T
协变。您还需要使用C#4.0。

这是一个非常常见的问题。让我们重命名您的类型:

abstract class Fruit { }                    // was BaseViewPresenter
abstract class FruitBowl<T> where T : Fruit // was BaseView
class Apple : Fruit { }                     // was LoginPresenter
class BowlOfApples : FruitBowl<Apple> {  }  // was LoginView
抽象类水果{}//是BaseViewPresenter
抽象类FruitBowl,其中T:Fruit//是BaseView
苹果类:水果{}//was登录Presenter

苹果碗:水果碗这是一个非常常见的问题。让我们重命名您的类型:

abstract class Fruit { }                    // was BaseViewPresenter
abstract class FruitBowl<T> where T : Fruit // was BaseView
class Apple : Fruit { }                     // was LoginPresenter
class BowlOfApples : FruitBowl<Apple> {  }  // was LoginView
抽象类水果{}//是BaseViewPresenter
抽象类FruitBowl,其中T:Fruit//是BaseView
苹果类:水果{}//was登录Presenter

我接受了Eric的答案,因为它很好地解释了为什么我想要的东西不可能实现,但我也认为我会分享我的解决方案,以防其他人遇到同样的问题

我从原始的
BaseView
类中删除了泛型类型参数,并创建了第二个版本的
BaseView
类,其中包括泛型类型参数和它的细节

第一个版本由my
.Resolve()
方法或其他不关心特定类型的代码使用,第二个版本由任何关心特定类型的代码使用,例如实现
BaseView

下面是一个示例,说明我的代码最终是如何显示的

// base classes
public abstract class BaseViewPresenter { }
public abstract class BaseView : UserControl 
{
    public BaseViewPresenter Presenter { get; set; }
}

public abstract class BaseView<T> : BaseView
    where T : BaseViewPresenter
{
    public new T Presenter
    {
        get { return base.Presenter as T; }
        set { base.Presenter = value; }
    }
}

// specific classes
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter> 
{
     // Can now call things like Presenter.LoginPresenterMethod()
}

// updated .Resolve method used for obtaining UI object
public BaseView Resolve(BaseViewPresenter presenter)
{
    var type = model.GetType();
    var viewType = _dataTemplates[type];

    BaseView view = Activator.CreateInstance(viewType) as BaseView;
    view.Presenter = presenter;

    return view;
}
//基类
公共抽象类BaseViewPresenter{}
公共抽象类BaseView:UserControl
{
public BaseViewPresenter演示程序{get;set;}
}
公共抽象类BaseView:BaseView
其中T:BaseViewPresenter
{
新公共电视节目主持人
{
获取{return base.Presenter as T;}
设置{base.Presenter=value;}
}
}
//特定类别
公共类登录Presenter:BaseViewPresenter{}
公共部分类LoginView:BaseView
{
//现在可以调用Presenter.LoginPresenterMethod()之类的函数
}
//已更新。用于获取UI对象的解析方法
公共BaseView解析(BaseViewPresenter presenter)
{
var type=model.GetType();
var viewType=_dataTemplates[type];
BaseView视图=Activator.CreateInstance(viewType)作为BaseView;
view.Presenter=演示者;
返回视图;
}

我接受了Eric的答案,因为它很好地解释了为什么我想要的东西不可能实现,但我也认为我会分享我的解决方案,以防其他人遇到同样的问题

我从原始的
BaseView
类中删除了泛型类型参数,并创建了第二个版本的
BaseView
类,其中包括泛型类型参数和它的细节

第一个版本由my
.Resolve()
方法或其他不关心特定类型的代码使用,第二个版本由任何关心特定类型的代码使用,例如实现
BaseView

下面是一个示例,说明我的代码最终是如何显示的

// base classes
public abstract class BaseViewPresenter { }
public abstract class BaseView : UserControl 
{
    public BaseViewPresenter Presenter { get; set; }
}

public abstract class BaseView<T> : BaseView
    where T : BaseViewPresenter
{
    public new T Presenter
    {
        get { return base.Presenter as T; }
        set { base.Presenter = value; }
    }
}

// specific classes
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter> 
{
     // Can now call things like Presenter.LoginPresenterMethod()
}

// updated .Resolve method used for obtaining UI object
public BaseView Resolve(BaseViewPresenter presenter)
{
    var type = model.GetType();
    var viewType = _dataTemplates[type];

    BaseView view = Activator.CreateInstance(viewType) as BaseView;
    view.Presenter = presenter;

    return view;
}
//基类
公共抽象类BaseViewPresenter{}
公共抽象类BaseView:UserControl
{
public BaseViewPresenter演示程序{get;set;}
}
公共抽象类BaseView:BaseView
其中T:BaseViewPresenter
{
新公共电视节目主持人
{
获取{return base.Presenter as T;}
设置{base.Presenter=value;}
}
}
//特定类别
公共类登录Presenter:BaseViewPresenter{}
公共部分类LoginView:BaseView
{
//现在可以调用Presenter.LoginPresenterMethod()之类的函数
}
//已更新。用于获取UI对象的解析方法
公共BaseView解析(BaseViewPresenter presenter)
{
var type=model.GetType();
var viewType=_dataTemplates[type];
BaseView视图=Activator.CreateInstance(viewType)作为BaseView;
view.Presenter=演示者;
返回视图;
}

我通常解决这个问题的方法是创建一个中间类,该类可以通过委托访问类型参数化类的方法。还可以通过getter/setter访问字段

总的模式是:

公共抽象类Super{}
公共抽象类MyAbstractType,其中T:Super{
公共MyGeneralType AsGeneralType(){
返回MyGeneralType.Create(此);
}
//根据上下文的不同,隐式cast操作符可能会
//看起来更好,尽管对某些口味来说可能太微妙了。
公共静态隐式运算符MyGeneralType(MyAbstractType t){
返回MyGeneralType.Create(t);
}
公共int字段;
public void MyMethod1(){}
公共void MyMethod2(int参数){}
公共抽象bool MyMethod3(字符串参数);
}
public委托T Getter();
公共委托无效设置器(T值);
聚氨基甲酸酯
Miu: meow
Snoopy: woof
Snuffles: meow
Fluffy: meow
Marley: woof
Megan: woof