170 похожих чатов

Вечер добрый. Знает ли кто-нибудь решение для такой задачи? Есть класс, в

методе которого последовательно нужно вызвать несколько generic методов.
В сущности, результат выполнения Build() зависит от того, что передается в качестве типов в AddState:
public class StateMachineBuilder
{
public IConfiguration Build()
{
var builder = new InternalBuilder();
builder.AddState<FirstState>();
builder.AddState<SecondState>();
builder.AddState<ThirdState>();
return builder.Build();
}
}

Чтобы билдер как-то параметризировать, можно сделать StateMachineBuilder или Build() generic. Но состояний может быть много и это может превратиться в Build<TFirstState, TSecondState, TThirdState, ...........TN_ndState>, что выглядит сомнительно. Можно ли упаковать перечисление передаваемых типов или передать их другим путем?

14 ответов

12 просмотров

я перефразирую вопрос за тебя - можно ли типизировать конечный автомат? Да, можно.

в чем именно проблема? зачем делать метод Build обобщенным? внутри метода Build есть какое-то требование знать типы?

Я понял. Спрашивается про внешний метод Build а не про внутренний (который builder.Build). Типоаргументы тут - не лучшая идея, потому что тогда нужно либо делать миллион перегрузок (и то можно не угадать), либо заранее знать количество состояний. Вижу два относительно нормальных варианта: 1. Сделать нормальный шаблон билдер, т.е. вынести AddState<T> в метод, потом в методе Build дергать только _internalBuilder.Build. Соответственно в такой ситуации напрашивается вопрос - зачем вообще огород городить и почему бы пользоваться сразу InternalBuilder, зачем вообще эта обертка в виде StateMachineBuilder нужна, какая ее функция? 2. Передавать в функцию аргументом лямбду. Будет выглядеть так: public IConfiguration Build(Func<InternalBuilder, InternalBuilder> configure) { var builder = new InternalBuilder(); builder = configure(builder); return builder.Build(); } И вызываться как-то так: stateMachineBuilder.Build(x => { x.AddState<FirstState>(); x.AddState<SecondState>(); return x; }); Понятно что при желании можно в лямбду принимать не инстанс InternalBuilder, а какую-то обертку над нам, чтобы не показывать пользователю какой-то ненужный ему апи (например метод Build). Но что-то тут уже много оберток получается, нужно с позиции здравого смысла и требований к задаче оценивать, какие из них нужны, а какими можно принебречь.

Vogl- Автор вопроса
Kirill Tolmachev
Я понял. Спрашивается про внешний метод Build а не...

Конечных автоматов может быть много. Схема переходов одна, а вот состояния могут быть разные. По сути, я передаю набор состояний и строиться автомат заданного вида

Vogl- Автор вопроса
Kirill Tolmachev
Я понял. Спрашивается про внешний метод Build а не...

Ну с заданной лямбдой можно и без билдера. А по месту сконфигурировать. Идея в том, чтобы на месте вызвать билд, передав набор состояний в виде типов. Кроме аддстейт много всего вызывается в качестве расширений для аддстейт. Оно во всех случаях одинаково. Разница только в передаваемом типе. Я не стал указывать остальной обвес ибо на суть вопроса не влияет.

Vogl
Конечных автоматов может быть много. Схема переход...

У тебя противоречивые показания > Схема переходов одна, а вот состояния могут быть разные В общем, пока что мы решаем не ту проблему

Vogl- Автор вопроса
Ayrat Hudaygulov
У тебя противоречивые показания > Схема переходов...

Почему протевочиво? Есть состояния один, два, три. Переходим мы из один в два из два в три. То, что мы так двигаемся по состояниям, описывается а конфигурации. А вот один, два и три могут быть разными (в состояниях переход не описывается). Да и на суть вопроса это не влияет. Главное, есть женерик методы, как прокинуть им классы

Vogl
Почему протевочиво? Есть состояния один, два, три....

На суть вопроса это очень влияет, т.к. ты видишь цель и не видишь препятствий. А надо бы сделать шаг назад и рассказать что ты делаешь. Вот мы выяснили что у тебя набор функций-переходов один и тот же, и они даже составляют одну и ту же схему переходов (почему я и говорил что у тебя противоречивые показания). Но ты хочешь в разных автоматах менять лейблы стейтов? Даже твой запрос выполнить элементарно, интерфейсы вместо конкретных стейтов принимай в твоих функциях перехода.

Vogl- Автор вопроса
Ayrat Hudaygulov
На суть вопроса это очень влияет, т.к. ты видишь ц...

В качестве стейта мы передаем не значение, а тип. В сущности, тут интерфейс не думаю, что поможет. Если абстрагироваться от задачи, то есть условно, десять женерик функций, которые вызываются в определенном порядке. Важное значение имеют передаваемые женерикам типы. Параметризация - передаваемые типы. Их не получиться обернуть внутрь класса, по понятной причине, а делать метод билд женериком - плохой вариант.

Vogl
В качестве стейта мы передаем не значение, а тип. ...

Признаюсь честно, от имплементации ты не сильно абстрагировался и пересказал её ещё раз, не рассказав что же ты делаешь. А теперь покажи почему это не работает interface Step1 Interface Step2 Interface Step3 1to2 :: Step1 -> Step2 2to3 :: Step2 -> Step3 3to1 :: Step3 -> Step1 type SuperStep1 = interface Step1 type SuperStep2 = interface Step2 type RealStep1 =   interface Step1 type RealStep2 =   interface Step2 1to2 SuperStep1() SuperStep2() 1to2 MyStep1() MyStep2() Как видишь - функции перехода одни и те же - набор стейтов разный Теперь тебе надо показать почему это не решение и мы может наконец узнаем что же ты делаешь

Vogl- Автор вопроса
Ayrat Hudaygulov
Признаюсь честно, от имплементации ты не сильно аб...

Окей, как сюда запихнуть такое решение Foo<здесь параметризуемый класс>()?

Vogl- Автор вопроса

Окей, получается? Build<State1, State2, State3....>() { Foo1<State1>(); Foo2<State2>(); Foo3<State3>();.... }

Vogl
Окей, получается? Build<State1, State2, State3.......

билд в твоей постановке задачи лишний Смотри https://t.me/DotNetRuChat/1529288 Уже всё есть и никакого билда не надо

Похожие вопросы

Обсуждают сегодня

Какой-то там пердун в 90-х решил, что есть какая-то разная типизация. Кого вообще это волнует?
КТ315
49
void terminal_scroll() { memmove(terminal_buffer, terminal_buffer + VGA_WIDTH, buffer_size - VGA_WIDTH); memset(terminal_buffer + buffer_size - VGA_WIDTH, 0, VGA_WIDTH); ...
Егор
47
Всем привет! Подскажите, пожалуйста, в чем ошибка? Настраиваю подключение к MySQL. Либы лежат рядом с exe. Все как по "учебнику"
Евгений
16
А можете как-то проверить меня по знаниям по ассемблеру?
A A
132
Здравствуйте! У меня появилась возможность купить книгу "Изучай Haskell во имя добра!". Но я где-то слышал, что эта книга устарела. Насколько это правда??
E
22
Здравствуйте! Я вот на stepic решаю задачи на хаскеле https://stepik.org/lesson/8443/step/8?unit=1578 мой код import Data.List (isInfixOf) removing :: String -> [String] ->...
E
10
Камрады, кто тесно работал с vtv, хотел уточнить. Ширина column задаётся жёстко на этапе создания дерева или можно в рантайме ее менять программно (не мышкой)?
Ed Doc
10
да ладно ... что там неочевидного ? глянуть в исх-ки датасета и/или кверика чтобы понять в каком месте и как выполняется обращения к св-вам blablaSQL - минутное дело, даже е...
Сергей
7
Здесь для arm кто-нибудь кодит ?
Nothing
52
Всем привет, у меня есть сервер принимающий входящие HTTP подключения, как проверить, что подключение было через прокси или нет, есть какие то поля в заголовках по которым мо...
Кибер Бомж
8
Карта сайта