在派生类中重新定义方法返回类型而不使用泛型

cmp*_*ken 0 c# inheritance partial-classes llblgen

长话短说:

是否有某种方法可以将抽象方法添加到基类中,从而允许派生类覆盖该方法的返回类型,而无需使用泛型,并且无需使用关键字new


我正在为 LLBLGen Pro 开发一些自定义模板。在此过程中,我拒绝更改 LLBLGen Pro 提供的默认模板,这样如果其他人选择实施我的模板,我的方法就不会覆盖他们的文件。

我开始处理(并取得了良好进展)的一项任务是开发一个为每个实体生成 DTO 的模板。沿着这些思路,一个目标是为我的实体提供一种ToDTO()方法。为了进行泛型编程,我决定在公共基类中定义此方法,这就是我的麻烦开始的地方。


请记住,ToDTO()在基类中定义方法的目的是因为我希望创建一个通用存储库(Fetch()例如,使用方法),我希望在该存储库中工作CommonEntityBase,而不是特定实体。


LLBLGen 定义其CommonEntityBase类如下:

public abstract partial class CommonEntityBase : EntityBase2 {
   // LLBLGen-generated code
}
Run Code Online (Sandbox Code Playgroud)

我最初的计划是将我的方法添加到另一个部分类中,如下所示:

public abstract partial class CommonEntityBase {
    public abstract CommonDTOBase ToDto();
}
Run Code Online (Sandbox Code Playgroud)

我认为继承的类能够将其方法中的返回类型定义为从基类的返回类型派生的类型,如下所示:

public partial class PersonEntity : CommonEntityBase {
    public override PersonDTO ToDto(){ return new PersonDTO(); }
}
Run Code Online (Sandbox Code Playgroud)

但是我错了


我的第二次尝试是使用泛型定义类,如下所示:

public abstract partial class CommonEntityBase<T> : CommonEntityBase 
      where T : CommonDTOBase {
   public abstract T ToDto();
}
Run Code Online (Sandbox Code Playgroud)

够简单的。我所要做的就是让生成的实体类继承这个新的实体库。只是一个警告。由于我不想覆盖 LLBLGen 的模板,因此又回到了部分类。

LLBLGen 的各个实体具有以下定义:

public partial class PersonEntity : CommonEntityBase {
   // LLBLGen-generated code
}
Run Code Online (Sandbox Code Playgroud)

这就是我的问题。为了使我的方法起作用,我必须使用以下定义创建我自己的部分类:

public partial class PersonEntity : CommonEntityBase<PersonDTO> {
   public override PersonDTO ToDto(){ return new PersonDTO(); }
}
Run Code Online (Sandbox Code Playgroud)

当然,这是不可能的,因为据我现在所知

[分部类] 指定基类的所有部分都必须一致,但省略基类的部分仍然继承基类型。


我要尝试的第三件事是简单地使用new关键字覆盖基类的函数定义:

public abstract partial class CommonEntityBase {
    public virtual CommonDTOBase ToDto(){ return null; }
}

public partial class PersonEntity : CommonEntityBase {
    public new PersonDTO ToDto(){ return new PersonDTO(); }
}
Run Code Online (Sandbox Code Playgroud)

然而,这完全违背了我的方法的目的,因为我希望能够在将PersonEntity'sToDTO()方法强制转换为CommonEntityBase. 通过这种方法,可以执行以下操作:

CommonEntityBase e = new PersonEntity();
var dto = e.ToDto();
Run Code Online (Sandbox Code Playgroud)

会导致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();
    }
}
Run Code Online (Sandbox Code Playgroud)

por*_*ges 5

代替:

public abstract partial class CommonEntityBase {
    public abstract CommonDTOBase ToDto();
}

public partial class PersonEntity : CommonEntityBase {
    public override PersonDTO ToDto(){ return new PersonDTO(); }
}
Run Code Online (Sandbox Code Playgroud)

为什么你不直接返回这样的 DTO:

public abstract partial class CommonEntityBase {
    public abstract CommonDTOBase ToDto();
}

public partial class PersonEntity : CommonEntityBase {
    // changed PersonDTO to CommonDTOBase
    public override CommonDTOBase ToDto(){ return new PersonDTO(); }
}
Run Code Online (Sandbox Code Playgroud)

我认为这对于 OO 代码来说更惯用。您是否需要知道 DTO 的确切类型?