TL;博士:
是否有某种方法可以向基类添加抽象方法,允许派生类覆盖方法的返回类型,而不使用泛型,并且不使用
new
关键字?
我正在为 LLBLGen Pro 开发一些自定义模板。在此过程中,我拒绝更改 LLBLGen Pro 提供的默认模板,这样我的方法就不会在其他人选择实现我的模板时覆盖他们的文件。
我开始从事的一项任务(并取得了良好的进展)是开发一个模板,该模板为每个实体生成一个 DTO。按照这些思路,一个目标是为我的实体提供一种ToDTO()
方法。为了通用编程,我决定在一个公共基类中定义这个方法,这就是我的麻烦开始的地方。
请记住,ToDTO()
在基类中定义方法的目的是因为我希望创建一个通用存储库(Fetch()
例如,使用一个方法),我希望它可以在 中工作CommonEntityBase
,而不是特定实体.
LLBLGenCommonEntityBase
像这样定义它的类:
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(); }
}
但我错了。
我的第二次尝试是使用泛型定义类,如下所示:
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(); }
}
当然,这是不可能的,因为据我所知,
指定基类的[部分类]的所有部分必须同意,但省略基类的部分仍继承基类型。
我要尝试的第三件事是简单地用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
为空,这是我不想要的。
我遇到了各种讨论我的第一种方法的 链接,以及为什么它不起作用,并且通常指向我的通用方法作为一般意义上的解决方案。但是,在我的情况下,泛型似乎不起作用。
这一切都是为了问我想要完成的事情是否可行。
是否有某种方法可以向基类添加抽象方法,允许派生类覆盖方法的返回类型,而不使用泛型,并且不使用new
关键字?
或者也许我是从错误的角度来解决这个问题的,还有其他一些技术可以解决我的问题?
编辑
这是我想用Porges 的方法完成的实体的用例:
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();
}
}