LXF90 моно
Mono: Свързване на библиотеки
Създайте супер търсене в файлова система за по-малко от час? Нашият постоянен шеф на маймунитеПол Хъдсънправи невъзможното не само възможно, но и просто.
Съдържание
Вашата мисия, ако се заемете с нея, е да напишете конзолна програма, която индексира файловата система на потребителя във фонов режим, сканира поща, RSS емисии, хронология на браузъра и съдържание на файла и след това ви позволява да търсите всичко това със светкавична скорост. Схванах го? Добре, ще се видим след час - успех!
Това, което е страхотно за .NET, е възможността да застанете на раменете на гигантите, като използвате техните библиотеки. Разбира се, C също позволява това - например програматаArk RPGима библиотекаlibarkrpg0c2a, която позволява на други C програми да извикват нейните функции, вместо да ги внедряват отново. Но този подход не е без проблеми: напримерGstreamerе разделен на няколко библиотеки, всяка със собствен номер на версия. Типичен пример еlibgstdataprotocol-0.10.so.0.8.1. C не приема нови версии на библиотеки без актуализиране на самата програма, поради което номерата на версиите са толкова важни - не забравяйте да дадете на приложението сиlibgstdataprotocol-0.10, а не 0.9 или 0.11.
Mono позволява на програмистите просто да поискат "хайде, Beagle" и да получат каквато версия е налична. Този подход не винаги работи, особено с някои по-нови Linux приложения, които не са достигнали версия 1.0. Причината да имат толкова ниски номера на версиите (Beagle е на 0.2.14) е, че интерфейсът за програмиране на приложения (API) не е достатъчно стабилен. API е термин за имена на функции, типове параметри и връщани стойности за дадена библиотека. Стабилността на API означава, че ако функцията DoFoo() във версия 1.0 приема цяло числоаргумент и връща низ, тогава всяка програма, която го използва, ще работи с версия 1.01 на библиотеката, тъй като функцията не се променя.
Най-важното нещо в API е частта „I“, действителният интерфейс (име, параметри, върната стойност): ако е фиксирано, тогава няма значение как библиотеката изпълнява задачата си и оставете нейните версии да се променят, както искате.
- Ние използваме Mono и Beagle също, което означава, че имаме достъп до предимствата на Beagle.
- Beagle има API, който ни разкрива неговата функционалност, но не е стабилен и може да се промени в бъдеще (променен е доста драстично в миналото).
- За да използвате Beagle, всичко, което трябва да знаете, са имената на неговите функции и как да получите достъп до тях.
Все още ли ви е трудно? И това е така. Но аз обещах да ви науча на всички умения, от които се нуждаете, за да бъдете професионалист, до края на нашата поредица от уроци, така че нека се заемем с работата.
Нека започнем с името на нашето приложение. На монобазираните Gnome приложения им писна от имена с буквата G, така че реших да избера нещо забавно и напреднало. Предлагам Poochy, което е името на неясен персонаж с кучешка глава в игра на Nintendo (дори Майк не е чувал за него!), което пасва идеално на кучешката тема, дадена от Beagle. "хрътка"].
Така че стартирайте MonoDevelop, изберете File > Нов проект, след това C# > Конзолен проект, премахнете отметката от Създаване на отделна поддиректория за решение, след това въведете „Poochy“ в полето Име и щракнете върху бутона Нов в долната част. Ще получите доброто старо приложение Hello World - ние го „кодирахме“ в началото на поредицата от уроци; премахнете редовете Console.WriteLine() и оставете метода Main() празен.
GTK и командния ред
За този проект трябва да използвамеBeagleи - не се изненадвайте -GTK,затова щракнете с десния бутон върху Препратки в левия панел (точно надРесурси,AssemblyInfo.csиMain.cs) и изберете Редактиране на препратки. В прозореца, който се появява, преминете към раздела Пакети, където изберетеBeagle(версия 0.0.0.0 - предупредих ви, че далеч не е стабилна, нали?) иGTK-sharp(версия 2.10.0.0). Тези числа просто ви казват кои версии са инсталирани в момента - ако някой има различна версия наBeagle, Mono с удоволствие ще се задоволи с тази, която има.
Затова поискахме библиотекитеBeagleиGTK#да се използват, но за да ги използвате наистина, трябва да напишете изрази с помощта в началото на изходния код. По подразбиране единственият използван ред е
Системната библиотека включва основните функции за писане на конзолно приложение, включително достъп до самата конзола за осигуряване на I/O. Искаме да включимBeagleиGTKв този списък, така че добавете следните два реда:
В метода Main() трябва да извикатеBeagleи да му кажете какво да търси. Това може да стане чрез Query, специален обектBeagle. Този обект също знае как да изпълнява нашите собствени методи при настъпване на определени събития - например намиране на нещо, което съответства на заявка за търсене. Ето как изглежда всичко това в C# - поставете този код там, където беше Console.WriteLine():
Като цяло не е трудно, но не е цялата приказка: след като намери файл, RSS емисия или каквото и да е друго, което отговаря на нашата заявка,Beagleвинаги извиква метода OnHitsAdded() и когато приключи търсенето, ще извика метода OnFinished() - за да може кодът да се компилира, трябва да имплементирате и двата метода. За успешна компилация е достатъчно да вмъкнете два празни метода:
Обектите HitsAddedResponse и FinishedResponse всъщност даватмного полезна информация, но засега ще ги игнорираме. Нека продължим: натиснете F8, за да компилирате първото издание наPoochy(смело го наречете 0.1), след това отворете терминален прозорец и отидете до/dir/where/locates/poochy/bin/Debug. Време е да тестваме нашата хрътка.
Poochyтрябва да се стартира от командния ред, защото чете arg[0] , който трябва да предадем от командния ред. Изпълнете следната команда:
Тази команда ще накараBeagleда търси аргумента 'foo' в кеша си и ще отнеме около секунда за изпълнение на заявката (заменете foo с нещо, което знаете, че е в кеша наBeagle). Но тук ще откриете, че нищо не се извежда - нито файлове, нито нещо друго, съдържащо "foo". Чий е проблема - наБийгълили наш?Beagleе извън подозрение, така че проблемът е в нашия код. Ние разследваме.
Надпревара с времето
Нашата програма не работи по две причини. По-забележителен е празният метод OnHitsAdded(), извикан отBeagle, когато се намери съвпадение, в койтоPoochyтрябва да изведе резултата. Така Mono мълчи дори след като получи нещо отBeagle. Най-лесният начин еPoochyда изведе URL адреса на всеки обектBeagle, който намери, така:
Ако стартирате програмата, ще видите, че тя отново не произвежда нищо, въпреки чеBeagleтрябва да намери това, което поискахте. Проблемът е, че нашето търсене използва методаSendAsync(), което означава, чеBeagleизвършва търсенето асинхронно. Мислено превъртете програмата: компютърът изпълнява първия ред, преминава към втория, след това към третия и така нататък до края. Разбира се, понякога програмата скача от място на място, но въпросът е, че един ред код се изпълнява в даден момент.
Бийгълима двеметоди за търсене: синхронни и асинхронни. Първото означава „направете търсене и аз ще изчакам да приключи“, а второто означава „започнете търсене и аз ще продължа програмата; когато приключиш, прекъсни ме." Те са известни също като блокиращи и неблокиращи, тъй като синхронният метод блокира изпълнението на следващия ред, докато не завърши сам, докато асинхронният метод ви позволява да изпълнявате код, докато той работи паралелно.
Трябва да знаете това, за да отчетете тази възможност: какво ще стане, ако вашата програма приключи преди async методът да има време да направи нещо? Значи ще завърши предиBeagleда намери съвпадение? Отговорът е, че програмата ще излезе успешно и извиканият метод ще умре, преди да може да отпечата нещо. Ето защо не получихме никакъв резултат, което означава, че трябва да изчакамеБийгълда завърши търсенето.
Разбира се, разбрахте, че това е безкраен цикъл, но той не консумира почти никакво процесорно време и позволява на други части на приложението (GUI или, в нашия случай,Beagle) да работят пълноценно. Това е, което искаме, поради което ще седнем на главния цикъл на GTK: нека нашата програма не работи, докатоBeagleтърси и отпечатва резултата. За да направите това, добавете два реда в края на метода Main():
Този код казва на GTK да стартира и работи. Компилирайте програмата, като натиснете F8 и я стартирайте от командния ред. Този път трябва да получите списък с резултати, подобен на следния:
Две крачки напред, една назад
В допълнение към основния резултат получихме и страничен резултат: приложението не излиза. КогатоBeagleвърне всички възможни резултати, Poochy все още ще чака нещо. Видяхте ли, че основният цикълприложението е безкрайно и веднага щом извикахме метода Application.Run(), влязохме в състояние на вечно изпълнение. Докато програмата се срине, машината не се рестартира или не натиснете Ctrl+C,Poochyще остане в това състояние.
Може би това е, което искате - например искате периодично да проверявате ресурса или да изчакате, докато данните за търсене стигнат до вас през сокета. НоPoochyе проектиран да бъде програма, която търси при поискване и след това излиза. Вече написахме мъниче за метода OnHitsAdded, сега нека преминем към метода OnFinished(), който в момента е празен.
КогатоBeagleвърне всички резултати, той ще провери дали е регистриран метод за свойството FinishedEvent. Вече направихме това с нашия метод OnFinished(), който се извиква, когатоBeagleприключи. Сега трябва да кажем на GTK да напусне основния цикъл, така че нашето приложение да може да излезе елегантно. Доста е просто – ето как изглежда новият метод OnFinished():
Application.Quit() е метод на GTK, който прекъсва основния цикъл, изчиства всички използвани GTK ресурси (не много в нашия случай, тъй като не работим с графики), след което предава контрола на нашето приложение веднага след реда Application.Run() в метода Main(). Следователно пътят на програмата ще бъде както следва: Main() > SendAsync() > Application.Run() > GTK основен цикъл > OnFinished() > Application.Quit() > Главен() .
Компилирайте, стартирайте и се чудете на собствената си съобразителност: вашата програма прави всичко, което трябва да прави, и отне само десет реда смислен код!
Изчакайте. не всички!
Преди два урока разгледахме метода EndsWith(), приложен към низове, който приема низ като аргумент и връщаtrue, ако низ A завършва с низ B. Например:
Когато този код се изпълнява, baz ще бъде настроен наtrue, защото foo завършва на 'R'. .NET също има метод StartsWith(), който прави обратното, връщайкиtrue, ако един ред започва с друг. Оказва се, че можем да принудим нашия код да показва само файлове, като променим метода OnHitsAdded() на следния:
Това е метод на груба сила:Beagleтърси всичко и ние филтрираме резултатите преди показване. НоBeagleможе също да бъде научен да търси конкретен тип съвпадение с помощта на метода AddHitType(): той ще ви позволи да опишете това, което търсите в обикновен текст. Валидните опции включват Application , Calendar , Contact , Feeditem (за RSS), Image , IMLog , MailMessage и - това е! – Файл .
Връщайки се към метода Main(), намерете реда q.AddText(args[0]) и добавете следния ред пред него:
Стартирайте програмата и ще видите, че се показват само файлове - без кореспонденция от чатове, които замърсяват резултатите! LXF
ЧЗВ
Често задавани въпроси за моно - част I
Ако имате въпроси относно фините точки на Mono, ето отговорите.
- Не разбирам. Защо маркирахме Reference и след това също написахме реда с ?
Добавянето на нещо чрез Reference ви позволява да използвате съответния код; добавянето на нещо с помощта на реда спестява много код при извикване на методи. За да свържетеBeagle, трябва да го добавите като референция - тогава неговите обекти и методи ще станат достъпни и ние можем веднага да ги използваме, но само под напълно квалифицирано име, включително препратка към пространството от имена. Линията, използваща Beagle; казва на .NET, че когато пишем Query, се приема Beagle.Query. В нашия случай спестяванемалък; но, например, алгоритъмът SHA1 в .NET е в пространството System.Encryption.Cryptography и ще трябва да напишете System.Encryption.Cryptography.SHA1CryptoServiceProvider foo = new System.Encryption.Cryptography.SHA1CryptoServiceProvider() - съгласете се, доста досадно! Вместо това можете да поставите в началото с помощта на System.Encryption.Cryptography; , след това SHA1CryptoServiceProvider foo = new SHA1CryptoServiceProvider() . Не забравяйте, че MonoDevelop добавя System към Reference по подразбиране.
- Защо използваме += за добавяне на метод към събитието Beagle? Мислех, че += добавя стойност към променлива.
- Защо имам нужда от файл AssemblyInfo.cs?
Ще се смеете, но наистина има информация за вашата конструкция! В термините на .NET асемблито може да бъде или споделен обект (SO файл в Linux или DLL в Windows) или изпълним файл. Номерът на версията на вашия изпълним файл, името на програмиста и друга информация е в крайния двоичен файл и вие задавате всичко това в AssemblyInfo.cs.
- Трябва ли отварящите и затварящите фигурни скоби да са на отделни редове?