методе которого последовательно нужно вызвать несколько 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>, что выглядит сомнительно. Можно ли упаковать перечисление передаваемых типов или передать их другим путем?
я перефразирую вопрос за тебя - можно ли типизировать конечный автомат? Да, можно.
в чем именно проблема? зачем делать метод 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). Но что-то тут уже много оберток получается, нужно с позиции здравого смысла и требований к задаче оценивать, какие из них нужны, а какими можно принебречь.
Конечных автоматов может быть много. Схема переходов одна, а вот состояния могут быть разные. По сути, я передаю набор состояний и строиться автомат заданного вида
Ну с заданной лямбдой можно и без билдера. А по месту сконфигурировать. Идея в том, чтобы на месте вызвать билд, передав набор состояний в виде типов. Кроме аддстейт много всего вызывается в качестве расширений для аддстейт. Оно во всех случаях одинаково. Разница только в передаваемом типе. Я не стал указывать остальной обвес ибо на суть вопроса не влияет.
У тебя противоречивые показания > Схема переходов одна, а вот состояния могут быть разные В общем, пока что мы решаем не ту проблему
Почему протевочиво? Есть состояния один, два, три. Переходим мы из один в два из два в три. То, что мы так двигаемся по состояниям, описывается а конфигурации. А вот один, два и три могут быть разными (в состояниях переход не описывается). Да и на суть вопроса это не влияет. Главное, есть женерик методы, как прокинуть им классы
На суть вопроса это очень влияет, т.к. ты видишь цель и не видишь препятствий. А надо бы сделать шаг назад и рассказать что ты делаешь. Вот мы выяснили что у тебя набор функций-переходов один и тот же, и они даже составляют одну и ту же схему переходов (почему я и говорил что у тебя противоречивые показания). Но ты хочешь в разных автоматах менять лейблы стейтов? Даже твой запрос выполнить элементарно, интерфейсы вместо конкретных стейтов принимай в твоих функциях перехода.
В качестве стейта мы передаем не значение, а тип. В сущности, тут интерфейс не думаю, что поможет. Если абстрагироваться от задачи, то есть условно, десять женерик функций, которые вызываются в определенном порядке. Важное значение имеют передаваемые женерикам типы. Параметризация - передаваемые типы. Их не получиться обернуть внутрь класса, по понятной причине, а делать метод билд женериком - плохой вариант.
Признаюсь честно, от имплементации ты не сильно абстрагировался и пересказал её ещё раз, не рассказав что же ты делаешь. А теперь покажи почему это не работает 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() Как видишь - функции перехода одни и те же - набор стейтов разный Теперь тебе надо показать почему это не решение и мы может наконец узнаем что же ты делаешь
Окей, как сюда запихнуть такое решение Foo<здесь параметризуемый класс>()?
Окей, получается? Build<State1, State2, State3....>() { Foo1<State1>(); Foo2<State2>(); Foo3<State3>();.... }
билд в твоей постановке задачи лишний Смотри https://t.me/DotNetRuChat/1529288 Уже всё есть и никакого билда не надо
Обсуждают сегодня