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
?
Возможно, я подхожу к этому с неправильного угла, и есть какая-то другая техника, которая могла бы решить мои проблемы?
EDIT
Вот вариант использования для того, что я хотел бы достичь с субъектами, принимая 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();
}
}
У вас, похоже, есть некоторые концептуальные проблемы с «частичными» классами. Магии нет; Я думаю, что лучший способ подумать о них состоит в том, что компилятор просто накапливает весь код, определенный для частичного класса, в одно определение класса перед компиляцией. – porges
Google «ковариантные типы возврата». –