【发布时间】:2011-03-08 17:42:16
【问题描述】:
TL;DR:
有没有办法在基类中添加一个抽象方法,允许派生类覆盖方法的返回类型,而不使用泛型,并且不使用
new关键字?
我正在为 LLBLGen Pro 开发一些自定义模板。在此过程中,我拒绝更改 LLBLGen Pro 提供的默认模板,以便我的方法不会覆盖其他人选择实施我的模板时的文件。
我已经开始着手(并取得了良好进展)的一项任务是开发一个为每个实体生成 DTO 的模板。按照这些思路,一个目标是为我的实体提供ToDTO() 方法。为了泛型编程,我决定在一个公共基类中定义这个方法,这就是我的麻烦开始的地方。
请记住,在基类中定义 ToDTO() 方法的目的是因为我希望创建一个我想要的通用存储库(例如,使用 Fetch() 方法)让CommonEntityBase 工作,而不是特定实体。
LLBLGen 像这样定义它的CommonEntityBase 类:
public abstract partial class CommonEntityBase : EntityBase2 {
// LLBLGen-generated code
}
我最初的计划是将我的方法添加到另一个部分类中,如下所示:
public abstract partial class CommonEntityBase {
public abstract CommonDTOBase ToDto();
}
我认为继承的类将能够在其方法中将返回类型定义为从基类的返回类型派生的类型,如下所示:
public partial class PersonEntity : CommonEntityBase {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
但是I was wrong.
我的第二次尝试是使用泛型定义类,如下所示:
public abstract partial class CommonEntityBase<T> : CommonEntityBase
where T : CommonDTOBase {
public abstract T ToDto();
}
足够简单。我所要做的就是让我生成的实体类继承自这个新的实体库。只有一个警告。由于我不想覆盖 LLBLGen 的模板,所以它回到了部分类。
LLBLGen 的各个实体有这样的定义:
public partial class PersonEntity : CommonEntityBase {
// LLBLGen-generated code
}
这就是我的问题。为了使我的方法起作用,我必须使用以下定义创建自己的部分类:
public partial class PersonEntity : CommonEntityBase<PersonDTO> {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
当然,这是不可能的,因为,as I now know,
指定基类的[部分类]的所有部分必须同意,但省略基类的部分仍继承基类型。
我要尝试的第三件事是简单地用 new 关键字覆盖基类的函数定义:
public abstract partial class CommonEntityBase {
public virtual CommonDTOBase ToDto(){ return null; }
}
public partial class PersonEntity : CommonEntityBase {
public new PersonDTO ToDto(){ return new PersonDTO(); }
}
但是,这完全违背了我的方法的目的,因为当PersonEntity 的ToDTO() 方法被转换为CommonEntityBase 时,我希望能够访问它。用这种方法,做:
CommonEntityBase e = new PersonEntity();
var dto = e.ToDto();
会导致dto 为空,这是我不想要的。
我遇到过variouslinks 讨论我的第一种方法,以及为什么它不起作用,并且通常将我的通用方法作为一般意义上的解决方案。但是,在我的情况下,泛型似乎不起作用。
所有这些都是为了问我想要完成的事情是否可能。
有没有办法在基类中添加抽象方法,允许派生类覆盖方法的返回类型,不使用泛型,也不使用new 关键字?
或者也许我从错误的角度来解决这个问题,还有其他一些技术可以解决我的问题?
编辑
这是我想用实体完成的用例,采用Porges's 方法:
public class BaseRepository<D,E> where D : CommonDTOBase where E : CommonEntityBase,new
public D Get(Guid id){
var entity = new E();
entity.SetId(id);
// LLBLGen adapter method; populates the entity with results from the database
FetchEntity(entity);
// Fails, as entity.ToDto() returns CommonDTOBase, not derived type D
return entity.ToDto();
}
}
【问题讨论】:
-
您似乎对
partial类有一些概念上的问题。没有魔法。我认为考虑它们的最佳方式是,编译器只是在编译之前为部分类定义的所有代码填充到一个类定义中。 -
谷歌“协变返回类型”。
标签: c# inheritance partial-classes llblgen