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)
正确解析为myLoginView
的新实例,但是控件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