Я не думаю, что могу ответить на этот вопрос вообще, для любого типа приложения или фреймворка, но я могу предложить ответ, который конкретно говорит об AutoFixture, а также предложить некоторые предположения о других сценариях использования.
Если бы мне сегодня пришлось писать AutoFixture с нуля, я бы поступил иначе.В частности, я бы не создавал повседневный API-интерфейс для чего-то вроде ISpecimenBuilder
.Скорее, я бы разработал API для манипулирования данными вокруг концепции функторов и монад, как указано здесь .
. Этот дизайн полностью основан на обобщениях, но для него требуются статически типизированные строительные блоки(также описанный в статье), известный во время компиляции.
Это тесно связано с тем, как работает что-то вроде QuickCheck .Когда вы пишете тесты на основе QuickCheck, вы должны предоставить генераторы для всех ваших собственных пользовательских типов.Haskell не поддерживает приведение значений во время выполнения, но вместо этого полагается исключительно на универсальные шаблоны и некоторую автоматизацию во время компиляции.Конечно, дженерики Haskell являются более мощными, чем C #, поэтому вы не можете обязательно передавать знания, полученные из Haskell, в C #.Тем не менее, он предполагает, что можно писать код полностью, не полагаясь на приведение во время выполнения.
Однако AutoFixture поддерживает определяемые пользователем типы без необходимости написания пользовательских генераторов.Это делается через .NET Reflection.В .NET API Reflection нетипизирован;все методы для генерации объектов и вызова элементов принимают object
в качестве ввода и возвращают object
в качестве вывода.
Любое приложение, библиотека или инфраструктура, основанные на Reflection, должны будут выполнять некоторое приведение во время выполнения.Я не понимаю, как обойти это.
Можно ли написать генераторы данных без Reflection?Я не пробовал следующее, но, возможно, можно было бы принять стратегию, в которой можно было бы написать «код» для генератора данных непосредственно в IL и использовать Reflection emit для динамической компиляции сборки в памяти, которая содержитгенераторы.
Это немного похоже на работу контейнера Hiro , IIRC.Я полагаю, что можно было бы спроектировать другие типы универсальных сред на основе этой концепции, но я редко вижу, как это делается в .NET.