TL;DR:
ジェネリックを使用せず、
new
キーワードを使用せずに、派生クラスがメソッドの戻り値の型をオーバーライドできるようにする抽象メソッドを基本クラスに追加する方法はありますか?
LLBLGen Pro 用のカスタム テンプレートの開発に取り組んでいます。その過程で、LLBLGen Pro が提供するデフォルトのテンプレートを変更することを拒否します。そのため、他の人が私のテンプレートを実装することを選択した場合に、私のアプローチによって他の人のファイルが上書きされることはありません。
私が取り組み始めた (そして順調に進んでいる) タスクの 1 つは、エンティティごとに DTO を生成するテンプレートを開発することです。これらの方針に沿って、目的の 1 つは私のエンティティに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(); }
}
しかし、私は間違っていました。
私の2番目の試みは、ジェネリックを使用してクラスを定義することでした。
public abstract partial class CommonEntityBase<T> : CommonEntityBase
where T : CommonDTOBase {
public abstract T ToDto();
}
十分に単純です。私がしなければならないことは、生成されたエンティティ クラスがこの新しいエンティティ ベースから継承されるようにすることだけです。1つだけ注意してください。LLBLGen のテンプレートを上書きしたくないので、部分クラスに戻ります。
LLBLGen の個々のエンティティには、次の定義があります。
public partial class PersonEntity : CommonEntityBase {
// LLBLGen-generated code
}
ここに私の問題があります。メソッドを機能させるには、次の定義で独自の部分クラスを作成する必要があります。
public partial class PersonEntity : CommonEntityBase<PersonDTO> {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
もちろん、これは不可能です。 なぜなら、私が今知っているように、
基本クラスを指定する [部分クラスの] 部分はすべて一致する必要がありますが、基本クラスを省略した部分は依然として基本型を継承します。
3 番目に試みたのは、基本クラスの関数定義を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();
null になってしまいdto
ますが、これは望ましくありません。
私の最初のアプローチと、それがうまくいかない理由について議論しているさまざまな リンクに出くわしました。通常、一般的な意味での解決策として私の一般的なアプローチを指しています。ただし、私の状況では、ジェネリックは機能していないようです。
これはすべて、私が達成しようとしていることが可能かどうかを尋ねるためのものです。
ジェネリックを使用せず、new
キーワードを使用せずに、派生クラスがメソッドの戻り値の型をオーバーライドできるようにする抽象メソッドを基本クラスに追加する方法はありますか?
それとも、間違った角度からこれに取り組んでいるのかもしれません。私の問題を解決できる他のテクニックがありますか?
編集
ポージェスのアプローチを採用して、エンティティで達成したいことのユースケースを次に示します。
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();
}
}