В конце (учитывая ограничения, над которыми я работал) я фактически использовал вариацию на ряд тем выше.
Поскольку мне пришлось избегать любых ссылок на мой уровень доступа к данным из-за циклических ссылок, я в итоге сделал что-то с делегатами и «фабричным» кодом. Вписав его в свой исходный сценарий, я сделал следующее:
class Car
{
public void SetLookupProvider(ILookupProvider value) { _lookupProvider = value; }
public IMakeInfo Make { get { return _lookupProvider.ResolveMake(MakeId); } }
....
}
interface ILookupProvider
{
IMakeInfo ResolveMake(int id);
}
class LookupProvider
{
public delegate IMakeInfo ResolveMakeDelegate(int id);
public ResolveMakeDelegate ResolveMakeDel { set { _resolvemake = value; } }
public IMakeInfo ResolveMake(int id){ return _resolvemake(id); }
}
Тогда по моему заводскому методу ...
ICar returnedObject = new Car(blah, foo, bar, etc);
ILookupProvider luprovider = new LookupProvider();
luprovider.ResolveMakeDel = DataAccessLayer.FunctToGetMakeInfo;
(Car)returnedObject.SetLookupProvider(luprovider).
Теперь я первый, кто признает, что это не самое красивое решение (я бы выбрал методы Extension, если бы у меня был доступ к компилятору 3.0 ...), но он не связывает класс Car с уровнем DataAccess (что в моей ситуации предотвратило круговую ссылку ада ...). Класс Car не должен знать, как он получает результат, и фабричный метод, который в первую очередь создает объекты Car, - это единственное, что связано со слоем доступа к данным.
Я еще не пометил ответ, я позволю еще нескольким людям проголосовать, а затем пойти с самым высоким - особенно потому, что я думаю, что все они являются правильными ответами (просто я не мог использовать ни одного полностью в этот экземпляр).