У меня возникают некоторые проблемы при попытке «размножать» общий тип более чем на один уровень подклассов. У меня есть три уровня классов: GenericResponseDtoMapper<T>
- это абстрактный класс, а T
- это GenericSearchResponseDto
.Иерархическое использование генериков
У меня есть два подкласса, которые простираются GenericResponseDtoMapper
: SimpleResponseDtoMapper
и GroupedResponseDtoMapper
. В этих двух подклассах я вынужден указать общий тип; для istance Я должен написать:
SimpleResponseDtoMapper : GenericResponseDtoMapper<GenericResponseDtoMapper>
.
И наконец, у меня есть классы, которые расширяют SimpleResponseDtoMapper
и некоторые другие, которые расширяют GroupedResponseDtoMapper
. Моя проблема в том, что я не могу указать подтип GenericSearchResponseDto
на этом уровне.
Итак, как я управляю родовыми типами, чтобы оставить общий тип для первого и второго слоев классов, оставив более низкий уровень классов использовать указанный тип родового типа?
Вот код:
public abstract class GenericResponseDtoMapper<T> : IResponseDtoMapperDecorator where T : GenericSearchResponseDto
{
protected List<T> items;
public GenericResponseDtoMapper()
{
items = new List<T>();
}
public abstract IList<T> GetItems(IList<Entity.FullText_xml.DreDoc> documents);
}
Класс SimpleResponseDtoBuilder:
public abstract class SimpleResponseDtoBuilder : GenericResponseDtoMapper<GenericSearchResponseDto>
{
public SimpleResponseDtoBuilder() : base() { }
public override IList<GenericSearchResponseDto> GetItems(IList<DreDoc> documents)
{
foreach (var doc in documents)
{
var item = new GenericSearchResponseDto();
item.IdDatabank = doc.Field.IdDatabank;
item.IdDocMaster = doc.Field.IdDocMaster;
item.DescDatabank = doc.Field.DescDatabank;
item.Materie = doc.Field.MateriaAll.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
item = setResponseParams(item, doc);
items.Add(item);
}
return items;
}
public abstract GenericSearchResponseDto setResponseParams(GenericSearchResponseDto item, DreDoc doc);
}
И наконец конкретная реализация:
public class GiurisprudenzaResponseDtoBuilder : SimpleResponseDtoBuilder
{
private HighlightHelper _highLightHelper;
private const string _BR = @"<br/>";
public GiurisprudenzaResponseDtoBuilder() : base()
{
_highLightHelper = new HighlightHelper();
}
public override IList<GiurisprudenzaSearchResponseDto> GetItems(IList<DreDoc> documents)
{
return base.GetItems(documents);
}
public override GiurisprudenzaSearchResponseDto setResponseParams(GiurisprudenzaSearchResponseDto item, DreDoc doc)
{
item.IdUnitaDoc = doc.Field.IdUnitaDoc;
... some item.Something = doc.Something...
return item;
}
Эта проблема весьма симптоматично пытается решить слишком много проблем бизнеса в системе типа. Даже если вы можете заставить его работать, никто не поймет отношения между типами; если это сложнее, чем «корзина апельсинов, корзина яблок», то будущие программисты не поймут это легко. Спросите себя: «Если бы у меня не было дженериков, какие интерфейсы я использовал бы для решения этой проблемы?» и пусть это поможет вашему дизайну. –