Пошаговое руководство. Использование Visual F# для создания, отладки и развертывания приложения
Данное пошаговое руководство позволяет ознакомиться с принципами использования языка F# в среде Visual Studio вместе с платформой .NET Framework 4.5.
С помощью данного руководства можно ознакомиться с принципами использования Visual Studio для создания приложений на языке F# на примере исторического анализа данных об учетной ставке казначейства США.Пример начинается с анализа данных с помощью интерактивного окна F#. Затем создается и тестируется код, анализирующий данные, после чего добавляется интерфейсная часть на C#, на примере которой будет рассмотрена интеграция кода на F# с другими языками платформы .NET.
Обязательные компоненты
Ниже приведены компоненты, необходимые для выполнения данного пошагового руководства.
- Visual Studio
Примечание |
---|
На вашем компьютере названия некоторых элементов интерфейса пользователя Visual Studio или их расположение могут отличаться от указанных в нижеследующих инструкциях. Это зависит от имеющегося выпуска Visual Studio и используемых параметров. Дополнительные сведения см. в разделе Параметры Visual Studio. |
Создание скрипта на F#
Сначала создадим скрипт на языке F#.В меню Файл выберите пункты Создать и Файл.В диалоговом окне Новый файл выберите Сценарий в категории Общие в списке Установленные шаблоны, а затем выберите Файл скрипта F#.Нажмите кнопку Открыть, чтобы создать файл, а затем сохраните его под именем RateAnalysis.fsx.
Используйте API платформы .NET и F# для доступа к интернет-сайту Федеральной резервной системы США.Введите приведенный ниже код.
open System.Net open System.IO let url = sprintf "http://www.federalreserve.gov/datadownload/Output.aspx?rel=H15&series=bcb44e57fb57efbe90002369321bfb3f&lastObs=&from=&to=&filetype=csv&label=include&layout=seriescolumn" let req = WebRequest.Create(url, Timeout = 10000000) let resp = req.GetResponse() let stream = resp.GetResponseStream() let reader = new StreamReader(stream) let csv = reader.ReadToEnd()
Обратите внимание на следующее.
Строки и ключевые слова выделяются цветом.
После каждой точки (".") выводятся списки завершения.
Среда Visual Studio может дополнять имена методов и другие идентификаторы. Для этого достаточно нажать сочетание клавиш CTRL+ПРОБЕЛ или CTRL+J в процессе набора идентификатора.При использовании сочетания CTRL+J отображается список завершения.
При наведении указателя мыши на идентификатор в коде появится подсказка со сведениями об этом идентификаторе.
Если при нажатии клавиши F1 курсор находится внутри WebRequest, появится соответствующая документация.
Если при нажатии клавиши F1 курсор находится внутри let, появится соответствующая документация.
Ссылки на типы и пространства имен из библиотек mscorlib.dll, System.dll и System.Windows.Forms.dll присутствуют по умолчанию.
Задаваемое здесь значение Timeout является свойством, а не аргументом конструктора.F# позволяет задавать значения свойств подобным образом.
Если скопировать URL-адрес из примера в браузер, отобразится список значений с разделителями-запятыми, содержащий даты и значения учетной ставки, публикуемые Федеральной резервной системой США.
Теперь код следует запустить, используя F# Interactive.Выделите весь код (с помощью мыши или сочетания клавиш CTRL+A), щелкните его правой кнопкой мыши и выберите пункт Выполнение в интерактивном режиме.(Также можно нажать сочетание клавиш ALT+ВВОД.)
Появится окно F# Interactive (если оно не было открыто до этого).
Код успешно выполняется.
В окне F# Interactive отображается следующее.
val url : string = "http://www.federalreserve.gov/datadownload/Output.aspx?rel=H1"+[107 chars] val req : System.Net.WebRequest val resp : System.Net.WebResponse val stream : System.IO.Stream val reader : System.IO.StreamReader val csv : string = ""Series Description","Market yield on U.S. Treasury securities"+[224219 chars] >
Затем изучите данные с помощью F# Interactive.В командной строке F# Interactive введите команду csv;; и нажмите клавишу ВВОД.Введите команду csv.Length;; и нажмите клавишу ВВОД.Обратите внимание на следующее.
Данные отображаются по состоянию на текущий момент.
F# Interactive отображает значение и длину строки csv, как показано здесь.
07/10/2009, 3.32 07/13/2009, 3.38 07/14/2009, 3.50 07/15/2009, 3.63 " > csv.Length;; val it : int = 224513
На следующем рисунке показано окно F# Interactive.
Окно F# Interactive
Теперь создадим код F# для синтаксического анализа CSV-данных.CSV-файлы содержат значения с разделителями запятыми.В редакторе кода добавьте следующий код.Кроме того, добавьте open System.Globalization в начало файла.Выбирая добавленный в этом разделе код по мере ввода строк, можно просматривать частичные результаты, нажимая сочетание клавиш ALT+ВВОД.Обратите внимание на следующее.
IntelliSense предоставляет полезные сведения после ввода точки даже в сложных вложенных выражениях.
Если код не завершен (или некорректен), красное волнистое подчеркивание указывает на имеющиеся в нем синтаксические и семантические ошибки.
Конвейеры создаются с помощью оператора конвейеризации (|>).Оператор принимает значение, возвращаемое одним выражением, и использует его в качестве аргумента функции, стоящей в следующей строке.Конвейеры и F# Interactive упрощают частичное выполнение кода обработки данных.
let interest = csv.Split([|'\n'|]) |> Seq.skip 8 |> Seq.map (fun line -> line.Trim()) |> Seq.filter (fun line -> not (line.EndsWith("ND"))) |> Seq.filter (fun line -> not (line.Length = 0)) |> Seq.map (fun line -> line.Split([|','|])) |> Seq.map ( fun values -> System.DateTime.Parse(values.[0], CultureInfo.CreateSpecificCulture("en-US")), float values.[1])
Теперь данной функциональности нужно присвоить имя.Удалите последовательность идентификатора bcb44e57fb57efbe90002369321bfb3f из определения url и замените его на %s, чтобы превратить строку литералов в строку формата.Добавьте seriesID после строки формата.Выделите весь код, за исключением открытых директив, и нажмите клавишу TAB.Перед блоком кода с отступом добавьте следующие строки кода.
let loadRates maturity = // The following tuples associate various maturity durations, in years, // with codes defined for treasury bills by the Federal Reserve. let maturitiesMap = Map.ofList [(1, "e30653a4b627e9d1f2490a0277d9f1ac") (2, "c66ea77a2e8f0919c5133c7633065908") (5, "fbb02942bfdbff31a479e98bcbe26388") (10, "bcb44e57fb57efbe90002369321bfb3f") (20, "a1ebeb6e84ca6389772dd054dc980191")] let seriesID = Map.find maturity maturitiesMap
В конце блока кода с отступом добавьте interest.Обратите внимание на следующее.
Отступы в F# имеют особое значение.С их помощью задается уровень вложения.
Действие TAB практически аналогично Рефакторинг для извлечения метода (C#).
Код должен выглядеть примерно следующим образом.
open System.Net open System.IO let loadRates maturity = // The following tuples associate various maturity durations, in years, // with codes defined for treasury bills by the Federal Reserve. let maturitiesMap = Map.ofList [(1, "e30653a4b627e9d1f2490a0277d9f1ac") (2, "c66ea77a2e8f0919c5133c7633065908") (5, "fbb02942bfdbff31a479e98bcbe26388") (10, "bcb44e57fb57efbe90002369321bfb3f") (20, "a1ebeb6e84ca6389772dd054dc980191")] let seriesID = Map.find maturity maturitiesMap let url = sprintf "http://www.federalreserve.gov/datadownload/Output.aspx?rel=H15&series=%s&lastObs=&from=&to=&filetype=csv&label=include&layout=seriescolumn" seriesID let req = WebRequest.Create(url, Timeout = 10000000) let resp = req.GetResponse() let stream = resp.GetResponseStream() let reader = new StreamReader(stream) let csv = reader.ReadToEnd() let interest = csv.Split([|'\n'|]) |> Seq.skip 8 |> Seq.map (fun line -> line.Trim()) |> Seq.filter (fun line -> not (line.EndsWith("ND"))) |> Seq.filter (fun line -> not (line.Length = 0)) |> Seq.map (fun line -> line.Split([|','|])) |> Seq.map ( fun values -> System.DateTime.Parse(values.[0], CultureInfo.CreateSpecificCulture("en-US")), float values.[1]) interest
Теперь данную функциональность следует использовать с новыми входными данными.Выделите весь код и нажмите сочетание клавиш ALT+ВВОД, чтобы выполнить его с помощью F# Interactive.В командной строке F# Interactive вызовите новую функцию loadRates применительно к новым годовым ставкам: 1, 2 и 5.Обратите внимание на следующее.
Прежние определения в F# Interactive не пропадают, но при этом также будут доступны новые.
Сложноструктурированные данные отображаются с помощью специальных функций вывода.
Разработка компонента с помощью F#
Создайте проект библиотеки для публикации созданной функциональности.В меню Файл выберите пункт Создать, а затем команду Проект.В диалоговом окне Создать проект выберите Visual F# в списке Установленные, а затем выберите Библиотека F#, чтобы создать новый проект библиотеки.Назовите проект RateAnalysis.Скопируйте ранее созданный код из файла RateAnalysis.fsx и вставьте его в файл Library1.fs.Добавьте объявление модуля в начало файла: module RateLoader.В Обозреватель решений переименуйте Library1.fs в RateLoader.fs и сохраните файл.Обратите внимание на следующее.
- Шаблон библиотеки F# по умолчанию содержит файл кода с расширением .fs и скрипт с расширением .fsx.Скрипт можно использовать для интерактивного тестирования кода библиотеки.
Теперь следует создать класс F#, предоставляющий необходимую функциональность.В обозревателе решений щелкните правой кнопкой мыши проект, выберите команду Добавить, затем Новый элемент.В диалоговом окне Добавление нового элемента выберите пункт Исходный файл F#.Назовите файл Analyzer.fs.В обозревателе решений щелкните правой кнопкой мыши файл Script.fsx и выберите команду Вниз.(Также можно нажать сочетание клавиш ALT+СТРЕЛКА ВНИЗ.) Вставьте в файл Analyzer.fs следующий код:
module RateAnalysis.Analyzer open RateLoader /// Provides analysis of historical interest rate data. type Analyzer(ratesAndDates) = let rates = ratesAndDates |> Seq.map snd /// Construct Analyzer objects for each maturity category. static member GetAnalyzers(maturities) = maturities |> Seq.map loadRates |> Seq.map (fun ratesAndDates -> new Analyzer(ratesAndDates)) member sa.Min = let date, minRate = (Seq.minBy (fun (_, rate) -> rate) ratesAndDates) (minRate, date.ToString("d")) member sa.Max = let date, maxRate = (Seq.maxBy (fun (_, rate) -> rate) ratesAndDates) (maxRate, date.ToString("d")) member sa.Current = rates |> List.ofSeq |> List.rev |> List.head
Обратите внимание на следующее.
- F# поддерживает ряд понятий из объектно-ориентированного программирования.Дополнительные сведения см. в разделах Классы (F#), Наследование (F#), а также других статьях из справочника по языку F#.
Чтобы построить проект, нажмите сочетание клавиш CTRL+SHIFT+B или клавишу F6.Обратите внимание на следующее.
Построение проекта выполняется успешно.
В окне "Список ошибок" отсутствуют ошибки.
В каталоге вывода появляются файлы .dll, .pdb и .xml.
В окне вывода отображается следующее:
------ Build started: Project: RateAnalysis, Configuration: Debug Any CPU ------ C:\Program Files (x86)\Microsoft F#\v4.0\fsc.exe -o:obj\Debug\RateAnalysis.exe -g --debug:full --noframework --define:DEBUG --define:TRACE --optimize- --tailcalls- -r:"C:\Program Files (x86)\Microsoft F#\v4.0\FSharp.Core.dll" -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll" -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll" --target:exe --warn:3 --warnaserror:76 --vserrors --utf8output --fullpaths --flaterrors Program.fs RateLoader.fs ValueAnalyzer.fs RateAnalysis -> C:\Users\ghogen\Documents\Visual Studio 10\Projects\RateAnalysis\RateAnalysis\bin\Debug\RateAnalysis.exe ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
Чтобы добавить клиентское приложение C#, откройте контекстное меню для узла решения и выберите Добавить, а затем выберите Создать проект.В диалоговом окне Добавить новый проект выберите Visual C# в списке Установленные шаблоны, а затем выберите Консольное приложение.Можно развернуть узел Другие языки.Назовите проект CSharpDriver, а затем нажмите кнопку ОК.Откройте контекстное меню узла Ссылки данного проекта, а затем выберите Добавить ссылку.Выберите узел Решение, а затем выберите узел Проекты.Установите флажок рядом с проектом RateAnalysis, а затем нажмите кнопку ОК.Откройте контекстное меню для узла проекта CSharpDriver, а затем нажмите кнопку Назначить запускаемым проектом.Введите следующий код в теле метода Main в приложении C#.
var maturities = new[] { 1, 2, 5, 10 }; var analyzers = RateAnalysis.Analyzer.Analyzer.GetAnalyzers(maturities); foreach (var item in analyzers) { Console.WriteLine("Min = {0}, \t Max = {1}, \t Current = {2}", item.Min, item.Max, item.Current); } Console.WriteLine("Press Enter to exit."); Console.ReadLine();
Обратите внимание на следующее.
Между C# и F# можно добавлять межпроектные ссылки.
Пространства имен и типы , определенные на языке F#, можно использовать в коде на языке C# обычным образом.
Документирующие комментарии F# доступны в IntelliSense для C#.
C# имеет доступ к кортежным возвращаемым значениям из API F#.Кортежи — это значения типа Tuple в платформе .NET Framework 4.5.
Для отладки приложения нажмите клавишу F11, чтобы построить его, запустить в отладчике и перейти к первой строке выполняемого кода.Нажимайте клавишу F11, пока не будет достигнут код F# в теле члена GetAnalyzers.Обратите внимание на следующее.
Можно легко переходить из кода C# в код F#.
Каждое выражение F# представляет в отладчике отдельный шаг.
Значения maturities отображаются в окне "Локальные".
При последующих нажатиях клавиши F11 продолжается отладка оставшейся части приложения.
Такие команды отладчика, как Выполнить до курсора, Задать следующий оператор, Вставить точку останова, Добавить контрольное значение и К дизассемблированному коду, работают ожидаемым образом.
Развертывание приложения
Если вы по-прежнему в режиме отладки, то останове отладку путем нажатия SHIFT + F5 или открыв меню Отладка а затем выбрав Остановить отладку.
Откройте контекстное меню для проекта CSharpDriver, а затем выберите Свойства.
В конструкторе проектов выберите вкладку Опубликовать, которая отображает параметры развертывания приложения.
Нажмите кнопку Мастер публикации.
Запустится мастер публикации, и на первом экране запрашивается, куда нужно публиковать файлы.
В текстовом поле укажите расположение на жестком диске, куда будут перемещены установочные файлы после публикации, или выберите кнопку Обзор, чтобы перейти к расположению.
Нажмите кнопку Готово, чтобы принять все значения по умолчанию для построения стандартной установки, которая может быть распространена на клиентские машины или нажмите кнопку Далее чтобы просмотреть остальные параметры публикации.
Исполняемый файл установки и вспомогательные файлы публикуются в заданном расположении.
Следующие действия
Начать писать код на F# можно с прочтения статьи Пошаговое руководство. Создание первой программы на F# или знакомства с функциями F# в статье Функции как значения первого класса (F#).Изучить язык F# можно, прочитав Справочник по языку F#.