Я пытаюсь создать общий конвертер типов. Все типы будут иметь базовый класс Entity
и интерфейс IConvertable
. Я реализовал интерфейс для объектов, которые могут быть преобразованы:Какова правильная конструкция для замены статического вызова на общие типы?
public interface IConvertable
{
public bool CanConvert<TTarget>() where TTarget : Entity, IConvertable
Tuple<bool, Entity> TryConvertTo<TTarget> where TTarget: Entity, IConvertable
}
Идея заключается в том, что каждый конкретный подкласс Entity (partial
классов, автоматически сгенерированный код, я не могу напрямую изменять) будет иметь CanConvert<TTarget>
, который определит, может ли он быть преобразован в целевой тип.
Я пытался собрать общий тип преобразователя, который будет принимать IEnumerable
х Entity
, превращая их (и выполнение других задач, в то же время - например, через другие интерфейсы, reparenting), а затем возвращаются преобразованная Entity
классы.
Моя первоначальная реализация в том, что, по сути, CanConvert<TTarget>
является static
, в том, что она всегда постоянна от А TSource
к TTarget
, поэтому, когда я строю свой конвертер:
public class EntityConverter<TSource, TTarget> where TSource : Entity, IConvertable
where TTarget : Entity, IConvertable
{
private IEnumerable<TSource> Records { get; set; }
public EntityConverter(IEnumerable<TSource> records) {
if (!TSource.CanConvert<TTarget>()) {
// error condition, reporting, etc.
}
Add(records);
}
public void Add(IEnumerable<TSource> records) { ... }
public void Convert() {
// massively simplified for example - there will actually be a store
// holding, more functionality, parent-child relationships, but
// this is the basic principle
for (var c in convertables) {
c.TryConvertTo<TTarget>();
}
}
}
Очевидно, что есть много причин, почему static
функции не могут использоваться на дженериках (Eric Lipperts отличные описания из этого доступны onhisblog), однако это оставляет меня в quandry - как я могу определить что-то, что описывает тип (не экземпляр) и может ссылаться на тип, в общей структуре, без массивные внешние partial
конструкции или злые фабрики - это предполагается быть доступной, повторно используемой структурой, чем кто-либо может звонить из другого класса, просто расширяя типы partial
с реализацией интерфейса.
Я подозреваю, что просматриваю вещи не так, но я не вижу, что. Как определить, является ли преобразование типа действительным, не имея чего-то другого в середине для хранения преобразований типа?
Редактировать Немного обновили образец кода (ранее было преобразование в конструкторе). На самом деле, я делаю это преобразование совсем немного позже, поскольку у меня есть несколько источников конвертируемых файлов, которые необходимо добавить до фактического преобразования. Это приводит к фактической ошибке (если !CanConvert<TTarget>()
), идущей довольно далеко по линии. Для каждого экземпляра этого класса он будет преобразовываться из типа TSource
в TTarget
, поэтому справедливость этого преобразования должна быть известна в конструкторе, и это должно быть ошибкой в конструкторе, а не во время преобразования позже ... По крайней мере , это мое чтение о вещах.
Благодаря @Dennis за разъяснение некоторых из моих мыслей о вещах ... Я могу закончить все это, но я не чувствую, что я далеко. Я подумал о том, чтобы поставить CanConvert<TTarget>()
в функцию Add()
... которая чувствует, что я почти там ...
Что не так с просто вызовом 'CanConvert' для каждого экземпляра в' convertables'? Это было бы более правильным, потому что некоторая 'TBase' не может быть преобразована в' TSomething', тогда как 'TDerived: TBase'. –
примечание стороны: не использовать кортеж. 'bool TryConvertTo (вне результата Entity)' является лучшим дизайном –
Кроме того, я не уверен, что переход 'convertables' в конструктор - лучший подход. Вероятно, это должен быть метод. И ваши заметки о других операциях («на самом деле есть магазин // холдинг, больше функциональности») предполагают возможное нарушение «EntityConverter» https://en.wikipedia.org/wiki/Single_responsibility_principle. Конвертер должен конвертировать только то, что предлагает его название. –