Предыстория:
Итак, я застрял в архитектурной проблеме за последние пару ночей на рефакторе, с которым я играл.Ничего важного, но это беспокоит меня.На самом деле это упражнение DRY , и попытка довести его до такой степени, что архитектура DAL полностью DRY.Это полностью философское / теоретическое упражнение.
Код частично основан на одном из рефакторингов @ JohnMacIntyre , о которых я недавно убедил его написать в блоге на http://whileicompile.wordpress.com/2010/08/24/my-clean-code-experience-no-1/. IЯ немного изменил код, как обычно, для того, чтобы продвинуть код на один уровень дальше - обычно просто для того, чтобы увидеть, какой дополнительный пробег я могу извлечь из концепции ... в любом случае, мои причины в значительной степени не имеют значения.
Часть моего уровня доступа к данным основана на следующей архитектуре:
abstract public class AppCommandBase : IDisposable { }
Содержит базовые элементы, такие как создание объекта команды и очистка после удаления AppCommand.Все мои объекты базы команд являются производными от этого.
abstract public class ReadCommandBase<T, ResultT> : AppCommandBase
Это содержит базовые вещи, которые влияют на все команды чтения - особенно в этом случае, чтение данных из таблиц и представлений.Без редактирования, без обновления, без сохранения.
abstract public class ReadItemCommandBase<T, FilterT> : ReadCommandBase<T, T> { }
Это содержит некоторые более базовые общие вещи, такие как определение методов, которые потребуются для чтения одного элемента из таблицы в базе данных, где имя таблицы, имя ключевого поля и имена списка полей определяются как обязательные абстрактные свойства (которые должны быть определены производным классом.
public class MyTableReadItemCommand : ReadItemCommandBase<MyTableClass, Int?> { }
Это содержит конкретные свойства, которые определяют имя моей таблицы, список полей из таблицы илиview, имя ключевого поля, метод для анализа данных из строки IDataReader в моем бизнес-объекте и метод, который инициирует весь процесс.
Теперь у меня также есть эта структура для моего ReadList...
abstract public ReadListCommandBase<T> : ReadCommandBase<T, IEnumerable<T>> { }
public class MyTableReadListCommand : ReadListCommandBase<MyTableClass> { }
Разница в том, что классы List содержат свойства, относящиеся к генерации списка (т. Е. PageStart, PageSize, Sort и возвращает IEnumerable) по сравнению с возвратом одного объекта DataObject (для которого требуется только фильтр).который идентифицирует уникальную запись).
Проблема:
Я ненавижу, что яв моем классе MyTableReadListCommand есть несколько свойств, которые идентичны в моем классе MyTableReadItemCommand.Я думал о переносе их в вспомогательный класс, но хотя это может централизовать содержимое членов в одном месте, у меня все равно будут идентичные члены в каждом из классов, которые вместо этого будут указывать на вспомогательный класс, который мне все еще не нравится.
Моей первой мыслью было, что двойное наследование решит эту проблему хорошо, хотя я согласен, что двойное наследование обычно является запахом кода, но это решит эту проблему очень элегантно.Итак, учитывая, что .NET не поддерживает двойное наследование, куда мне идти дальше?
Возможно, другой рефакторинг будет более подходящим ... но у меня возникают проблемы, когда я пытаюсь обойти голову.эта проблема.
Если кому-то нужна полная база кода, чтобы увидеть, о чем я пишу, у меня есть прототип решения для моего DropBox по адресу http://dl.dropbox.com/u/3029830/Prototypes/Prototype%20-%20DAL%20Refactor.zip. Код, о котором идет речь, находится вПроект DataAccessLayer.
PS Это не часть текущего активного проекта, это скорее головоломка для моего собственного развлечения.
Заранее спасибо, ребята, я ценю это.