Натройка конфига в блокноте — это шедеврально. Посоветуйте им хотя Nodepad++. А вообще, предложите им свои услуги по настройке.
Мы разворачиваем на разных компах, что-то у нас, что-то у заказчика, но всегда стараемся минимизировать ручное редактирование конфига. Плюс, конфигурационный файл должен содержать только ту информацию, которая нужна данному конкретному микросервису. Т.о. образом конфиг не разбухает, до неимоверных размеров.
А если создается что-то новое, более-менее часто, то как скопировав tt в новый проект, у вас уже все сгенерированно.
Новый проект — новый конфиг. А учитывая движение в сторону микросервисов, то получается, что и конфиги почти пыстые. Максимум 5-7 микросервисов (это мой опыт) и всякие частные настройки для конкретного сервиса. Т.о. повторное использование tt тут не подходит. Да и любое повторное использование кода не подходит. Конфиг почти каждый раз пишется с 0.
Надо сгенерировать mock config для тестов — поменяли пару строчек в шаблоне и он вам тестовые классы сделал.
Посмотрите мой ответBronx. Там я описываю, как создавать конфиги для разных целей без особых усилий.
В общем, пока я не увидел преимущество автоматической генерации конфигурационных классов с из заполнением. Скорей всего, тут кто к чему привык, ибо серебрянной пули не существует…
Ну и самое главное, это не единичный шаблон, а часть общей системы которая позволяет автоматизировать рутинные части.
Вот после этого я спорить не буду ибо согласен. Если есть смысл и возможность, то надо генерить.
Если я правильно понял, то все эти приемы направлены чтобы превратить мегагромадный конфиг во что-то удобоваримое…
Опыт как раз в том, что огромный конфиг пытались разбить на подконфиги и тем самым только усугубив проблему, вместо того, чтобы разобраться в чем причина. А проблема-то была в том, что система взяла на себя слишком много (получился этакий монолит-гигант) и плюс не было нормального деплоймента (конфиги ручками менялись для debug, test, sandbox и пр). Зато потом, когда все-таки разбили этот кусок гиганта на сервисы (мини или микро — это пожеланию), то монстрообразный конфиг пропал. Вместо него появились несколько мелких конфигов и для каждой среды свой конфиг.
Пример:
app.config — это конфигурация у разработкича
app.Release.config — это для всех остальных (тест, релиз и пр)
При деплое меням переменные в указанном конфиге. Например, при деплое тестировщикам имеем конфиг вида
Если я правильно понял, то вот этот длинный код создает класс с одной переменной и распарсивает значение из конфига.На мой взгляд как-то не рационально.
Также, если мы захотим добавить еще логики, то мы должны менять tt? Например, повторные адреса игнорировать. Можно, конечно, написать partial class и там реализовать метод со всякими проверками, а в tt его только дергать… По-моему как-то слишком сложно. Учитывая, что конфиг это та часть программы, которая очень редко меняется.
З.Ы. Еще раз спасибо за пример — буду разбираться.
Если в конфигурационном файле будет жлемент, а в классах его не будет, то система сгенерит Exception. Таким образом происходит проверка конфига и классов.
Под «рантаймом» я понимаю, когда программа запущена и она сама меняет ее конфиг. Вот я именно против этого. А вот когда в процессе развертывания кто-то меняет конфиг, так это я «за». Например, мы создаем релизный конфиг и там указываем заменить connectionString на реальзое значение в зависимости от среды развертывания. Что-то мне подсказывает, что в этом вопросе мы по одну сторону баррикады.
Что касается <clear/> и configSource… Я с этимт «параметрами» сталкивался очень давно и опыт был негативным, так что я стараюсь их избегать. Более того, это лично мое мнение, задвать в конфигурации, то что конфигурация в таком-то файле как-то странновато. Смысл данного действия для меня представляется только в том, чтобы разделить Debug от Release, ну, или разные конфиги для разных клиентов. Все это легко делается путем создания конфигурационного файла с разметкой и, в момент создания билда, автоматически подставляем нужные параметры.
Интересный подход. По-сути, вы написали свою «библиотеку», подобной ConfigurationParser, но на Т4.
Кстати, а если в Т4 появляется ошибка, то как тестировать? Несколько раз посоздавали разные конфиги и на этом все?
На и в догонку, а как быть если адреса почты написаны через точку с запятой, а в системе они должны быть с листе, да еще и проверены с помощью RegEx?
И на последок, если это не коммерческая тайна, то можно взглянуть на код?
Как правило это работает на маленький проекта без автоматических билдов и развертываний или в самом начале разработки, когда приложение опять-таки маленькое. Когда приложение разрастается до несколько десятков сервисов, да еще и с подключением к сотне других сторонних программ… Вот тут и начинается, что надо бы такую настроечку, а вот тут при чтении конфигурации обязательно проверить, что переменные в Octopuse имеют правильные значения и получается, что изначальные 10 строчек кода в разных проектах превращабтся в 20 в одном, 50 в другом, 10 в третьем, причем от исходных может вообще ничего не остаться.
Неплохая утилита, но есть как минимум два «но».
1. Читает json.
2. Нужен .NET Core
Мне больше всего не нравится то, что конфигураци хранится в json файлах… Сейчас попробую объяснить почему.
При создание проекта в .NET автоматически будет создан app.config, в который студия поместит какие-то свои данные. Затем, например, мы добавим WCF сервис и в том же файле увидим его параметры. При этом, давайте предположим, что мы используем самописный ORM и поэтому строку подключения можем хранить где угодно и мы выбрали json… Как-то выглядит, что настройки расползлись по двум файлам вместо одного…
Пользователя и не надо туда слать. Для этого существуют другие места. App.Config предназначен для хранения настроек приложения и очень хорошо с этим справлется. Добавляем к нему build-сервер (например, TeamCity) и Octopus (мне он нравится) и мы получаем развертывание приложения в один клик/чекин для разных сред (Dev, Test, Sandbox, Release). Поэтому я не понимаю почему он вам так не нравится…
Основное предназначение этой библиотеки — чтение настроек приложения, поэтому методы сохранения не предусмотрены.
Если честно, то я не стрононник что-либо менять в конфиге приложения в рантайме. Если что-то и надо заменить, то, используя, например, TeamCity+Octopus, создаем релиз и деплоим его с измененными настройками. Это относится к настройкам приложения.
Если же речь идет о пользовательских, то, как правило эти данные хранятся в БД и выходят за рамки данной либы.
[PropertyMapping("Folders ")]
public List<Folders> NewFolders { get; set; }
Это означает, что в конфигу мы ищем Folders и грузим данные в NewFolders.
Хотя, если честно, то я почти не сталкивался с ситуациями, когда надо было поменять имя… Вот структуру — это да, частое явление. То мы храним это в Листе, то давайте сделаем словарь…
Обратите внимание, что я нигде не использовал ключи а-ля «Folders», что, с моей точки хрения, уменьшает ошибку при копипасте.
На простых примерах можно использовать различные подходы и они будут примерно равнозначны. Все интересное начинается, когда конфигрурация разрастается и там появляются вложенные настройки, а в них еще вложенные и т.д.
Да, соглашусь, что можно input.Split(';').ToList();
Однако, я хотел акцентрировать внимание на то, что в этом методе можно написать любую логику. Например, в текущем примере мы можем добавить проверку правильность email'ов и сгенерить Exception если что-то не так.
Да, соглашусь, что можно input.Split(';').ToList();
Однако, я хотел акцентировать внимание на то, что в этом методе можно написать любую логику. Например, в текущем примере мы можем добавить проверку правильность email'ов и сгенерить Exception если что-то не так.
Используем myAppSettings.ConnectionString по своему усмотрению.
Это очень простой пример, но даже в нем нам приходится собственноручно создавать объект с настройками и заполнять его. Библиотека все это сделает за нас.
Все усложняется, когда появляются настройки со многими вложенностями. Например, в моем текущем проекте у нас в зависимости от страны — свои настройки, в которых прописываются подключения к различные сторонним сервисам, строки подключения к БД и тд. В результате чего для загрузки конфигурационного файла пришлось бы писать очень много кода, а так — создал классы и загрузил все одной строчкой.
Listrigon правильно ответил про стандартную систему конфигурационных файлов .NET. От себу лишь слегка добавлю, что в .NET для хранения конфигурации используется App.Config, в котором и записывается все настройки. Формат хранения данных — XML.
Более подробно можно прочитать здесь:
1. https://msdn.microsoft.com/en-us/library/1xtk877y.aspx
2. https://msdn.microsoft.com/en-us/library/ms254494(v=vs.110).aspx
Мы разворачиваем на разных компах, что-то у нас, что-то у заказчика, но всегда стараемся минимизировать ручное редактирование конфига. Плюс, конфигурационный файл должен содержать только ту информацию, которая нужна данному конкретному микросервису. Т.о. образом конфиг не разбухает, до неимоверных размеров.
Новый проект — новый конфиг. А учитывая движение в сторону микросервисов, то получается, что и конфиги почти пыстые. Максимум 5-7 микросервисов (это мой опыт) и всякие частные настройки для конкретного сервиса. Т.о. повторное использование tt тут не подходит. Да и любое повторное использование кода не подходит. Конфиг почти каждый раз пишется с 0.
Посмотрите мой ответ Bronx. Там я описываю, как создавать конфиги для разных целей без особых усилий.
В общем, пока я не увидел преимущество автоматической генерации конфигурационных классов с из заполнением. Скорей всего, тут кто к чему привык, ибо серебрянной пули не существует…
Вот после этого я спорить не буду ибо согласен. Если есть смысл и возможность, то надо генерить.
Опыт как раз в том, что огромный конфиг пытались разбить на подконфиги и тем самым только усугубив проблему, вместо того, чтобы разобраться в чем причина. А проблема-то была в том, что система взяла на себя слишком много (получился этакий монолит-гигант) и плюс не было нормального деплоймента (конфиги ручками менялись для debug, test, sandbox и пр). Зато потом, когда все-таки разбили этот кусок гиганта на сервисы (мини или микро — это пожеланию), то монстрообразный конфиг пропал. Вместо него появились несколько мелких конфигов и для каждой среды свой конфиг.
Пример:
При деплое меням переменные в указанном конфиге. Например, при деплое тестировщикам имеем конфиг вида
В Octopus'e задаем значение для CurrentConnectionString
Нажимаем на кнопку и деплоим куда надо. Переменная заменится на нужное значение автоматом.
А тем временем позвольте немного критики.
Если я правильно понял, то вот этот длинный код создает класс с одной переменной и распарсивает значение из конфига.На мой взгляд как-то не рационально.
Также, если мы захотим добавить еще логики, то мы должны менять tt? Например, повторные адреса игнорировать. Можно, конечно, написать partial class и там реализовать метод со всякими проверками, а в tt его только дергать… По-моему как-то слишком сложно. Учитывая, что конфиг это та часть программы, которая очень редко меняется.
З.Ы. Еще раз спасибо за пример — буду разбираться.
Если в конфигурационном файле будет жлемент, а в классах его не будет, то система сгенерит Exception. Таким образом происходит проверка конфига и классов.
Что касается <clear/> и configSource… Я с этимт «параметрами» сталкивался очень давно и опыт был негативным, так что я стараюсь их избегать. Более того, это лично мое мнение, задвать в конфигурации, то что конфигурация в таком-то файле как-то странновато. Смысл данного действия для меня представляется только в том, чтобы разделить Debug от Release, ну, или разные конфиги для разных клиентов. Все это легко делается путем создания конфигурационного файла с разметкой и, в момент создания билда, автоматически подставляем нужные параметры.
Кстати, а если в Т4 появляется ошибка, то как тестировать? Несколько раз посоздавали разные конфиги и на этом все?
На и в догонку, а как быть если адреса почты написаны через точку с запятой, а в системе они должны быть с листе, да еще и проверены с помощью RegEx?
И на последок, если это не коммерческая тайна, то можно взглянуть на код?
Но, все равно, спасибо за комментарий и ссылку на статью.
1. Читает json.
2. Нужен .NET Core
Мне больше всего не нравится то, что конфигураци хранится в json файлах… Сейчас попробую объяснить почему.
При создание проекта в .NET автоматически будет создан app.config, в который студия поместит какие-то свои данные. Затем, например, мы добавим WCF сервис и в том же файле увидим его параметры. При этом, давайте предположим, что мы используем самописный ORM и поэтому строку подключения можем хранить где угодно и мы выбрали json… Как-то выглядит, что настройки расползлись по двум файлам вместо одного…
Пользователя и не надо туда слать. Для этого существуют другие места. App.Config предназначен для хранения настроек приложения и очень хорошо с этим справлется. Добавляем к нему build-сервер (например, TeamCity) и Octopus (мне он нравится) и мы получаем развертывание приложения в один клик/чекин для разных сред (Dev, Test, Sandbox, Release). Поэтому я не понимаю почему он вам так не нравится…
Если честно, то я не стрононник что-либо менять в конфиге приложения в рантайме. Если что-то и надо заменить, то, используя, например, TeamCity+Octopus, создаем релиз и деплоим его с измененными настройками. Это относится к настройкам приложения.
Если же речь идет о пользовательских, то, как правило эти данные хранятся в БД и выходят за рамки данной либы.
Это означает, что в конфигу мы ищем Folders и грузим данные в NewFolders.
Хотя, если честно, то я почти не сталкивался с ситуациями, когда надо было поменять имя… Вот структуру — это да, частое явление. То мы храним это в Листе, то давайте сделаем словарь…
З.Ы. Забыл упомянуть об этом аттрибуте в статье.
На мой взгляд прелесть в том, что кода становится меньше.
Для примера возьмем секцию из статьи по вашей ссылке
Создадим классы
Вызовем загрузчик
Ну и как бы все :) Мы загрузили все настройки.
Обратите внимание, что я нигде не использовал ключи а-ля «Folders», что, с моей точки хрения, уменьшает ошибку при копипасте.
На простых примерах можно использовать различные подходы и они будут примерно равнозначны. Все интересное начинается, когда конфигрурация разрастается и там появляются вложенные настройки, а в них еще вложенные и т.д.
Да, соглашусь, что можно input.Split(';').ToList();
Однако, я хотел акцентрировать внимание на то, что в этом методе можно написать любую логику. Например, в текущем примере мы можем добавить проверку правильность email'ов и сгенерить Exception если что-то не так.
Да, соглашусь, что можно input.Split(';').ToList();
Однако, я хотел акцентировать внимание на то, что в этом методе можно написать любую логику. Например, в текущем примере мы можем добавить проверку правильность email'ов и сгенерить Exception если что-то не так.
В мире .NET разработчики привыкли работать с объектами. Поэтому практически в любом приложении можно встретить строчки
Используем myAppSettings.ConnectionString по своему усмотрению.
Это очень простой пример, но даже в нем нам приходится собственноручно создавать объект с настройками и заполнять его. Библиотека все это сделает за нас.
Все усложняется, когда появляются настройки со многими вложенностями. Например, в моем текущем проекте у нас в зависимости от страны — свои настройки, в которых прописываются подключения к различные сторонним сервисам, строки подключения к БД и тд. В результате чего для загрузки конфигурационного файла пришлось бы писать очень много кода, а так — создал классы и загрузил все одной строчкой.
Listrigon правильно ответил про стандартную систему конфигурационных файлов .NET. От себу лишь слегка добавлю, что в .NET для хранения конфигурации используется App.Config, в котором и записывается все настройки. Формат хранения данных — XML.
Более подробно можно прочитать здесь:
1. https://msdn.microsoft.com/en-us/library/1xtk877y.aspx
2. https://msdn.microsoft.com/en-us/library/ms254494(v=vs.110).aspx