რატომ არის საჭირო სწორი კოდი და როგორ აღმოიფხვრას ვალიდაციის შეცდომები
აპლიკაციის ლოკალიზებული რესურსები
რესურსები, როგორიცაა სურათები და სიმებიანი ცხრილები, შეიძლება განთავსდეს რესურსების ფაილებში ან ქვეასამბლეებში. ეს რესურსები შეიძლება იყოს ძალიან სასარგებლო აპლიკაციების ლოკალიზაციისას და .NET გთავაზობთ ჩაშენებულ მხარდაჭერას ლოკალიზებული რესურსების მოსაძებნად.
სანამ განვიხილავთ, თუ როგორ გამოვიყენოთ რესურსები აპლიკაციების ლოკალიზაციისთვის, მოდით, პირველ რიგში გადავხედოთ რესურსების შექმნისა და წაკითხვის ტექნიკას ენის გათვალისწინების გარეშე.
რესურსის ფაილების შექმნა
რესურსის ფაილებს შეუძლიათ შეინახონ ისეთი ელემენტები, როგორიცაა სურათები და სიმებიანი ცხრილები. რესურსის ფაილი შეიძლება იყოს ჩვეულებრივი ტექსტური ფაილი ან ფაილი .resX გაფართოებით, რომელიც იყენებს XML-ს. ეს სტატია ჯერ უყურებს მარტივი ტექსტური ფაილის ვარიანტს.
რესურსი, რომელიც მოიცავს სტრიქონების ცხრილს, შეიძლება შეიქმნას ჩვეულებრივ ტექსტურ ფაილში. ეს ფაილი უბრალოდ ანიჭებს სტრიქონებს კლავიშებს. გასაღები არის სახელი, რომელიც შეიძლება გამოყენებულ იქნას პროგრამაში შესაბამისი მნიშვნელობის მისაღებად. სივრცეები დაშვებულია გასაღებებსა და მნიშვნელობებში.
ქვემოთ მოცემულია მარტივი სიმებიანი ცხრილის შექმნის მაგალითი:
სათაური = პროფესიონალი C# საიტი = საიტი ავტორი = ალექს ეროჰინი
Resgen.exe პროგრამა
***.txt-დან რესურსის ფაილის შესაქმნელად, შეგიძლიათ გამოიყენოთ რესურსის ფაილის გენერირების სპეციალური პროგრამა Resgen.exe. მაგალითად, შეიტანეთ შემდეგი ბრძანება:
Resgen MyResources.txt
გამოიწვევს MyResources.resources ფაილის შექმნას. ამ პროგრამის მიერ გენერირებული რესურსის ფაილი შეიძლება დაემატოს ასამბლეას როგორც გარე ფაილი, ან ჩასვათ DLL ან EXE ასამბლეაში. Resgen პროგრამა ასევე მხარს უჭერს რესურსის ფაილების შექმნას XML ფორმატში .resX გაფართოებით. იგი გამოიყენება ძალიან მარტივად:
Resgen MyResources.txt MyResources.resX
ამ ბრძანების გაშვება შექმნის XML რესურსის ფაილს სახელად MyResources.resX.
Resgen პროგრამა მხარს უჭერს მკაცრად აკრეფილ რესურსებს. მკაცრად აკრეფილი რესურსი წარმოდგენილია როგორც კლასი, რომელიც წვდება რესურსებს. ასეთი კლასის შესაქმნელად, Resgen პროგრამა გთავაზობთ /str ვარიანტს:
Resgen /str:C#,MyResources.cs MyResources.resX
/str ოფციას უნდა მოჰყვეს ენა, სახელთა სივრცე, კლასის სახელი და წყაროს ფაილის სახელი, ამ თანმიმდევრობით.
Resgen პროგრამა არ უჭერს მხარს სურათების დამატების შესაძლებლობას. .NET Framework SDK მაგალითებს შორის არის ResXGen მაგალითი გაკვეთილებით. ResXGen-ში შეგიძლიათ მიმართოთ სურათებს .resX ფაილში. თქვენ ასევე შეგიძლიათ პროგრამულად დაამატოთ სურათები ResourceWriter ან ResXResourceWriter კლასების გამოყენებით, როგორც ეს მოგვიანებით იქნება ნაჩვენები.
ResourceWriter კლასი
რესურსის ფაილების შესაქმნელად Resgen უტილიტის გამოყენების ნაცვლად, შეგიძლიათ დაწეროთ სპეციალური პროგრამა, რომელიც ამის საშუალებას მოგცემთ. ResourceWriter კლასი System.Resources სახელთა სივრციდან გამოიყენება ორობითი რესურსის ფაილების შესაქმნელად, ხოლო ResXResourceWriter კლასი გამოიყენება XML-ზე დაფუძნებული რესურსის ფაილების შესაქმნელად. ორივე ეს კლასი მხარს უჭერს სურათების და სხვა სერიული ობიექტების დამატების უნარს. თუ იყენებთ ResXResourceWriter კლასს, მოგიწევთ მითითება System.Windows.Forms ასამბლეაზე.
შემდეგი კოდის მაგალითი აჩვენებს ResXResourceWriter ობიექტის შექმნას სახელად rw Demo.resx ფაილში. ინსტანციის შექმნის შემდეგ ResXResourceWriter კლასის AddResource() მეთოდის გამოყენებით, შეგიძლიათ დაიწყოთ რესურსების ნაკრების დამატება ჯამში 2 გბ-მდე. პირველი არგუმენტი AddResource()-ში საშუალებას გაძლევთ მიუთითოთ რესურსის სახელი, ხოლო მეორე საშუალებას გაძლევთ მიუთითოთ მნიშვნელობა. გამოსახულების რესურსი შეიძლება დაემატოს Image კლასის ინსტანციის გამოყენებით. იმისთვის, რომ შეძლოთ Image კლასის გამოყენება, თქვენ უნდა მიმართოთ System.Drawing ასამბლეას და ასევე დაამატოთ გამოყენების დირექტივა System.Drawing სახელთა სივრცის გასახსნელად.
აქ Image ობიექტი იქმნება logo.gif ფაილის გახსნით, ასე რომ თქვენ უნდა დააკოპიროთ გამოსახულების ფაილი შესრულებადი პროგრამის დირექტორიაში ან მიაწოდოთ მისი სრული გზა ImageToFile() მეთოდის არგუმენტად. გამოყენების განცხადება მიუთითებს, რომ გამოსახულების რესურსი ავტომატურად უნდა განადგურდეს გამოყენების ბლოკის ბოლოს.
შემდეგი, მარტივი სიმებიანი რესურსები ემატება ResXResourceWriter ობიექტს. და ბოლოს, ResXResourceWriter კლასის Close() მეთოდი ავტომატურად იძახებს ResXResourceWriter.Generate()-ს, რათა ჩაწეროს რესურსები Demo.resx ფაილში:
System.Drawing-ის გამოყენება; System.Resources-ის გამოყენებით; სახელთა სივრცე ProCSharp.Localization ( class Program ( static void Main() ( var rw = new ResXResourceWriter ("Demo.resx"); გამოყენებით (Image image = Image.FromFile ("logo.gif")) ( rw.AddResource("MyLogo" ", სურათი); rw.AddResource ("სათაური", "პროფესიული C#"); rw..AddResource ("ავტორი", "ალექს ეროჰინი"); rw.Close(); ) ) ))
ამ პატარა პროგრამის გაშვება შექმნის Demo.resx რესურსის ფაილს logo.gif სურათით შიგნით.
რესურსების ფაილების გამოყენება
თქვენ შეგიძლიათ დაამატოთ რესურსის ფაილები ასამბლეებში ან ბრძანების ხაზის C# შემდგენელის გამოყენებით csc.exe /resource ოფციით, ან პირდაპირ Visual Studio 2010-ში. იმისათვის, რომ ნახოთ, თუ როგორ უნდა იმუშაოთ რესურსების ფაილებთან Visual Studio 2010-ში, შექმენით კონსოლის აპლიკაციის პროექტი სახელად. რესურსის დემო.
დაამატეთ Demo.resx რესურსის ფაილი, რომელიც ადრე შექმენით ამ პროექტში Solution Explorer-ის ფანჯარაში კონტექსტური მენიუს გახსნით და არჩევით Add --> Add Existing Item. ნაგულისხმევად, ამ რესურსის Build Action თვისება დაყენდება ჩაშენებულ რესურსზე, რაც მიუთითებს, რომ ეს რესურსი უნდა იყოს ჩასმული გამომავალი ასამბლეაში.
შემდეგ, პროექტის პარამეტრებში (აპლიკაციის --> ასამბლეის ინფორმაციის არჩევით), თქვენ უნდა დააყენოთ ნეიტრალური ენის პარამეტრის მნიშვნელობა მთავარ ენაზე:
ამ პარამეტრის მნიშვნელობის შეცვლა დაამატებს ატრიბუტს assemblyinfo.cs ფაილში როგორც ქვემოთ:
ამ ატრიბუტის მნიშვნელობის დაყენება გააუმჯობესებს ResourceManager-ის მუშაობას, რაც საშუალებას მისცემს მას უფრო სწრაფად მოიძიოს რესურსები en-US-ისთვის და ასევე გამოიყენოს ისინი ნაგულისხმევ ვარიანტად. ამ ატრიბუტს ასევე შეუძლია განსაზღვროს ნაგულისხმევი რესურსის მდებარეობა კონსტრუქტორში მეორე პარამეტრის გამოყენებით. თქვენ შეგიძლიათ გამოიყენოთ UltimateResourceFallbackLocation ჩამოთვლა, რათა მიუთითოთ, რომ ის უნდა იყოს განთავსებული მთავარ ასამბლეაში (MainAssembly მნიშვნელობა) ან ქვეასამბლეაში (სატელიტის მნიშვნელობა).
პროექტის აშენების შემდეგ, შეგიძლიათ იხილოთ გენერირებული ასამბლეა ildasm უტილიტით და ნახოთ ატრიბუტი, .mresource, manifest-ში. ატრიბუტი.mresource აცხადებს ასამბლეის რესურსის სახელს. თუ .mresource გამოცხადებულია საჯარო (როგორც ამ მაგალითში), ეს ნიშნავს, რომ რესურსის ექსპორტი შესაძლებელია ასამბლეიდან და გამოყენებული იქნას სხვა ასამბლეებში კლასებში. თუ .mresource გამოცხადებულია კერძო, ეს ნიშნავს, რომ რესურსის ექსპორტი შეუძლებელია და ხელმისაწვდომია მხოლოდ ამ ასამბლეის ფარგლებში.
ჩაშენებულ რესურსზე წვდომისთვის იყენებთ ResourceManager კლასს, რომელიც მდებარეობს System.Resources სახელების სივრცეში. ამ კლასის კონსტრუქტორს შეუძლია არგუმენტად მიიღოს ასამბლეის სახელი, რომელიც შეიცავს რესურსებს.
ამ მაგალითში რესურსები ჩაშენებულია შესრულებად ასამბლეაში, ამიტომ მეორე არგუმენტმა მეთოდის შესრულების შედეგი უნდა გადასცეს კონსტრუქტორს. Assembly.GetExecutingAssembly(). პირველი არგუმენტი არის რესურსის ძირეული სახელი, რომელიც შედგება სახელთა სივრცის სახელისა და რესურსის ფაილის სახელისგან, მაგრამ რესურსის გაფართოების გარეშე. როგორც ადრე იყო ნაჩვენები, ამ სახელის ჩვენება შესაძლებელია ildasm უტილიტის გამოყენებით და უბრალოდ მისგან რესურსების გაფართოების ამოღებით. სახელის მიღება ასევე შესაძლებელია პროგრამულად, System.Reflection.Assembly კლასის GetManifestResourceNames() მეთოდის გამოყენებით:
სისტემის გამოყენება; System.Drawing-ის გამოყენებით; System.Reflection-ის გამოყენებით; System.Resources-ის გამოყენებით; სახელთა სივრცე Wrox.ProCSharp.Localization ( class Program ( static void Main() ( var rm = new ResourceManager ("Wrox.ProCSharp.Localization.Demo", Assembly.GetExecutingAssembly()); Console.WriteLine(rm.GetString("Title" ) Console.WriteLine(rm.GetString("Site")); .Save("logo.bmp"); (Bitmap ლოგო = Demo.MyLogo) ( logo.Save("logo.bmp"); ) ) )
მკაცრად აკრეფილი რესურსის შესაქმნელად მართული რესურსების რედაქტორიშეგიძლიათ შეცვალოთ პარამეტრის მნიშვნელობა წვდომის მოდიფიკატორიკოდის გარეშე თაობისგან საჯარო ან შიდა. თუ მნიშვნელობა დაყენებულია Public-ზე, გენერირებული კლასი აღჭურვილია საჯარო წვდომის მოდიფიკატორით და მისი წვდომა შესაძლებელია სხვა ასამბლეებიდან. როდესაც დაყენებულია Internal, გენერირებულ კლასს აქვს შიდა წვდომის მოდიფიკატორი და მისი წვდომა შესაძლებელია მხოლოდ იმ ასამბლეის შიგნიდან, რომელშიც ის მდებარეობს.
System.Resources სახელთა სივრცე
მოდით გადავხედოთ ყველა კლასს, რომელიც შეიცავს System.Resources სახელთა სივრცეში და საშუალებას გაძლევთ იმუშაოთ რესურსებთან.
რესურსების მენეჯერის კლასიშეიძლება გამოყენებულ იქნას ასამბლეებიდან ან რესურსების ფაილებიდან მიმდინარე კულტურისთვის სპეციფიკური რესურსების მოსაძიებლად. ResourceManager-ის გამოყენებით, შეგიძლიათ დაუყოვნებლივ მიიღოთ რესურსების მთელი ნაკრები კონკრეტული კულტურისთვის ResourceSet ინსტანციის სახით.
ResourceSet კლასისაშუალებას გაძლევთ წარმოადგინოთ რესურსების ნაკრები კონკრეტული კულტურისთვის. როდესაც ResourceSet ინსტანცირდება, ის ჩამოთვლის კლასის მიხედვით, ახორციელებს IResourceReader ინტერფეისს და ინახავს ყველა რესურსს HashTable-ში.
IResourceReader ინტერფეისიგამოიყენება ResourceSet-ში რესურსების სიაში. ResourceReader კლასი ახორციელებს ამ ინტერფეისს.
ResourceWriter კლასიგამოიყენება რესურსის ფაილის შესაქმნელად და ახორციელებს IResourceWriter ინტერფეისს.
ResXResourceSet, ResXResourceReader და ResXResourceWriter კლასებიResourceSet, ResourceReader და ResourceWriter კლასების მსგავსი, მაგრამ გამოიყენება არაორობითი რესურსის ფაილის შესაქმნელად და არა XML .resx ფაილის შესაქმნელად. რესურსის XML ფაილში ჩასმის ნაცვლად, ისინი საშუალებას გაძლევთ დაამატოთ მასზე მითითება ResXFileRef-ის გამოყენებით.
System.Resources.Tools სახელთა სივრცეშეიცავს StronglyTypedResourceBuilder კლასს, რომელიც შეიძლება გამოყენებულ იქნას რესურსიდან კლასის შესაქმნელად.
დოქტორი ლავლინსკი ნ.ე., შპს მეთოდი ლაბორატორიის ტექნიკური დირექტორი
ახლახან გამოქვეყნდა Preload ტექნოლოგიის ახალი სტანდარტი (ლინკი). ამ სპეციფიკაციის მთავარი მიზანი იყო დეველოპერს მიეცეს საშუალება დაარეგულირებინა გვერდის რესურსების ჩატვირთვის ლოგიკა.
წინა სტანდარტები
დატვირთვის მართვის იდეა ახალი არ არის. ადრე შემუშავებული იყო ტეგის რამდენიმე ვარიანტი ბმულიატრიბუტებით ქვე რესურსი, წინასწარი რენდერიდა წინასწარ ამოღება. თუმცა, ისინი ცოტა განსხვავებულად მუშაობდნენ: მათი დახმარებით შეგიძლიათ ჩატვირთოთ გვერდის ელემენტები ან მთელი გვერდები, რომლებიც შეიძლება საჭირო გახდეს საიტის შემდგომი ნავიგაციისთვის. ანუ ბრაუზერმა გაუგზავნა ასეთი მოთხოვნები დაბალი პრიორიტეტით და ბოლო. თუ საჭიროა პრიორიტეტის გაზრდა, მაშინ გადაწყვეტილებები არ იყო.
რესურსების ჩატვირთვა წინასწარ ჩატვირთვით
რას ითვალისწინებს ახალი სპეციფიკაცია? ჯერ ერთი, ახლა ჩატვირთვა ხდება იმის გარკვევით, თუ რა იტვირთება. რესურსის მითითებულ ტიპზე დაყრდნობით, ბრაუზერი ადგენს ჩამოტვირთვის პრიორიტეტს. Მაგალითად:
ბმული rel = "preload" href = "/js/script.js" as = "script" >ბმული rel = "preload" href = "/fonts/1.woff2" as = "font" type = "font/woff2" crossorigin>
მეორეც, რესურსის ტიპი ( როგორც) საშუალებას აძლევს ბრაუზერს გამოაგზავნოს სწორი სათაურები, რათა სერვერმა შეძლოს კონტენტის გაგზავნა უკეთესი შეკუმშვის ვარიანტებით (მაგალითად, გაგზავნოს WebP სურათები, თუ ბრაუზერი მხარს უჭერს მათ).
მეორე მაგალითში ჩვენ ვტვირთავთ შრიფტის ფაილს და მითითებულია კონკრეტული ფორმატი (WOFF2), რომელსაც ყველა ბრაუზერი არ უჭერს მხარს. თუმცა, სანამ წინასწარ ჩატვირთვის მექანიზმის მხარდაჭერა ემთხვევა ამ ფორმატის მხარდაჭერას, პრობლემები არ არის. მექანიზმის მიმდინარე მხარდაჭერა შეგიძლიათ ნახოთ.
შრიფტის უფრო სწრაფი ჩატვირთვა
წინასწარ ჩატვირთვის გამოყენებით ვებსაიტის დაჩქარების მაგალითია ღრმად ჩაფლული რესურსების ჩატვირთვა, როგორიცაა შრიფტები. ჩამოტვირთვის ნორმალურ პროცესში, ბრაუზერმა ჯერ უნდა ჩამოტვირთოს CSS ფაილი, რომელიც მიუთითებს შრიფტზე, გააანალიზოს ფაილი და შემდეგ რიგში დააყენოს მოთხოვნა შრიფტის ფაილის ჩამოსატვირთად.
თუ ამ შრიფტის წინასწარ ჩატვირთვას დავაზუსტებთ HTML გვერდის კოდში, ბრაუზერი გამოგიგზავნით მოთხოვნას HTML დოკუმენტის გაანალიზებისთანავე, რაც შეიძლება რამდენიმე წამით ადრე იყოს, ვიდრე ჩვეულებრივ შემთხვევაში. და ჩვენ ვიცით, რომ დანამატის შრიფტები ბლოკავს ელემენტებს და აყოვნებს შრიფტის რენდერირებას გვერდზე, ამიტომ საჭიროა მათი რაც შეიძლება სწრაფად ჩატვირთვა. ეს პრობლემა განსაკუთრებით მწვავეა HTTP/2-ის გამოყენებისას, როდესაც ბრაუზერი ერთდროულად უგზავნის ბევრ მოთხოვნას სერვერზე, რის შედეგადაც ზოგიერთ სურათს შეუძლია შეავსოს კლიენტის ზოლი და მნიშვნელოვანი რესურსების ჩატვირთვა შეფერხდება.
ასინქრონული CSS ჩატვირთვა
CSS ფაილები ყოველთვის ბლოკავს გვერდის რენდერს, ამიტომ ყველა CSS რესურსი, რომელიც შეიძლება გადაიდოს, შეიძლება ჩაიტვირთოს როგორც ჩვეულებრივი ფაილი და დინამიურად დაერთოს გვერდზე.
ეს კეთდება შემდეგნაირად:
ბმული rel = "preload" as="style" href = "async_style.css" onload = "this.rel="stylesheet"" >JS კოდის ჩატვირთვა შესრულების გარეშე
ასევე შეიძლება სასარგებლო იყოს JS სკრიპტის კოდის წინასწარ ჩატვირთვა, რათა მოგვიანებით შეასრულოთ იგი.
ეს შეიძლება გაკეთდეს შემდეგი კოდით:
ბმული rel = "წინასწარ ჩატვირთვა" როგორც = "script" href = "async_script.js" დატვირთვა = "var script = document.createElement("script"); script.src = this.href; document.body.appendChild(script);">ჩვენ განვიხილეთ წინასწარ ჩატვირთვის მექანიზმის გამოყენების ძირითადი გზები, მაგრამ შესაძლებლობები აქ არ ჩერდება, ჩაატარეთ საკუთარი ექსპერიმენტები!
ბოლო განახლება: 01/27/2016
რესურსები მნიშვნელოვან როლს თამაშობს WPF-ში. ამ შემთხვევაში რესურსები არ ნიშნავს დამატებით ფაილებს (ან ფიზიკური რესურსები), როგორიცაა აუდიო ფაილები, გამოსახულების ფაილები, რომლებიც ემატება პროექტს. აქ საუბარია ლოგიკური რესურსები, რომელსაც შეუძლია წარმოადგინოს სხვადასხვა ობიექტები - კონტროლი, ფუნჯები, ობიექტების კოლექციები და ა.შ. ლოგიკური რესურსების დაყენება შესაძლებელია XAML კოდში ან C# კოდში რესურსების თვისების გამოყენებით. ეს თვისება განსაზღვრულია FrameworkElement საბაზო კლასში, ამიტომ WPF კლასების უმეტესობას აქვს იგი.
რა აზრი აქვს რესურსების გამოყენებას? ისინი ზრდის ეფექტურობას: ჩვენ შეგვიძლია ერთხელ განვსაზღვროთ რესურსი და შემდეგ ხელახლა გამოვიყენოთ იგი აპლიკაციის სხვადასხვა ადგილას. ამ კუთხით მხარდაჭერა გაუმჯობესებულია - თუ რესურსის შეცვლის აუცილებლობაა, საკმარისია ამის გაკეთება ერთ ადგილას და ცვლილებები გლობალურად მოხდება აპლიკაციაში.
Resources თვისება წარმოადგენს ResourceDictionary ობიექტს, ან რესურსის ლექსიკონს, სადაც თითოეულ შენახულ რესურსს აქვს კონკრეტული გასაღები.
რესურსების განსაზღვრა
მოდით განვსაზღვროთ ფანჯრის რესურსი და ღილაკის რესურსი:
აქ ფანჯარაში ორი რესურსია განსაზღვრული: redStyle, რომელიც წარმოადგენს SolidColorBrush ობიექტს და gradientStyle, რომელიც წარმოადგენს ხაზოვან გრადიენტურ ფუნჯს. ღილაკს აქვს განსაზღვრული ერთი რესურსი, darkStyle, რომელიც წარმოადგენს SolidColorBrush-ს. გარდა ამისა, თითოეულ რესურსს უნდა ჰქონდეს x:Key თვისება, რომელიც განსაზღვრავს გასაღების ლექსიკონში.
და ბადის და ღილაკის Background თვისებებში, შესაბამისად, შეგვიძლია გამოვიყენოთ ეს რესურსები: Background="(StaticResource gradientStyle)" - აქ StaticResource გამოხატვის შემდეგ მოდის გამოყენებული რესურსის გასაღები.
რესურსების მართვა C# კოდში
მოდით დავამატოთ გრადიენტური ფუნჯი ფანჯრის რესურსების ლექსიკონში და დავაყენოთ იგი ღილაკზე:
// რესურსის ობიექტის განსაზღვრა LinearGradientBrush gradientBrush = new LinearGradientBrush(); gradientBrush.GradientStops.Add(new GradientStop(Colors.LightGray, 0)); gradientBrush.GradientStops.Add(new GradientStop(Colors.White, 1)); // ფანჯრის რესურსების ლექსიკონში რესურსის დამატება this.Resources.Add("buttonGradientBrush", gradientBrush); // ღილაკის ღილაკისთვის რესურსის დაყენება1.Background = (Brush)this.TryFindResource("buttonGradientBrush"); // ან ასე //button1.Background = (Brush)this.Resources["buttonGradientBrush"];
Add() თვისების გამოყენებით, brush ობიექტი და მისი თვითნებური გასაღები დაემატება ლექსიკონს. შემდეგ, TryFindResource() მეთოდის გამოყენებით, ვცდილობთ ვიპოვოთ რესურსი ლექსიკონში და დავაყენოთ ის ფონად. უფრო მეტიც, ვინაიდან ეს მეთოდი აბრუნებს ობიექტს, აუცილებელია შესრულდეს ტიპის ჩამოსხმა.
საერთო ჯამში, ResourceDictionary-ს აქვს შემდეგი მეთოდები და თვისებები:
მეთოდი დამატება (სტრიქონის გასაღები, ობიექტის რესურსი)ამატებს ობიექტს ლექსიკონში გასაღების გასაღებით და ნებისმიერი ობიექტი შეიძლება დაემატოს ლექსიკონს, მთავარია მას გასაღების შეხამება
Remove(string key) მეთოდი ამოიღებს რესურსს გასაღების კლავიშით ლექსიკონიდან
Uri თვისება ადგენს ლექსიკონის წყაროს
Keys თვისება აბრუნებს ლექსიკონში არსებულ ყველა გასაღებს
Values-ის თვისება აბრუნებს ლექსიკონში არსებულ ყველა ობიექტს
რესურსების კოლექციაში საჭირო რესურსის მოსაძებნად, თითოეულ ელემენტს აქვს FindResource() და TryFindResource() მეთოდები განსაზღვრული. ორივე აბრუნებს კონკრეტულ კლავიშის შესაბამის რესურსს. მათ შორის განსხვავება მხოლოდ ისაა, რომ FindResource() აყენებს გამონაკლისს, თუ სასურველი გასაღების მქონე რესურსი ვერ მოიძებნა. და TryFindResource() მეთოდი ამ შემთხვევაში უბრალოდ აბრუნებს null-ს.
საერთო რესურსები
როდესაც ერთი და იგივე რესურსი გამოიყენება სხვადასხვა ადგილას, ჩვენ რეალურად ვიყენებთ ერთსა და იმავე ობიექტს. თუმცა, ეს ყოველთვის არ არის სასურველი. ზოგჯერ აუცილებელია, რომ რესურსი განსხვავებულად იქნას გამოყენებული სხვადასხვა ობიექტზე. ანუ, ჩვენ გვჭირდება ცალკე რესურსის ობიექტის შექმნა თითოეული გამოყენებისთვის. ამ შემთხვევაში შეგვიძლია გამოვიყენოთ გამოთქმა x:Shared="False":
რესურსების გამოყენების მაგალითები
მოდით შევხედოთ რესურსების გამოყენების კიდევ რამდენიმე მაგალითს. მაგალითად, თუ გვინდა, რომ რამდენიმე ღილაკს ჰქონდეს იგივე თვისებები, მაშინ შეგვიძლია განვსაზღვროთ ერთი საერთო ღილაკი, როგორც რესურსი:
კიდევ ერთი მაგალითია ობიექტების სიის განსაზღვრა სიის ელემენტებისთვის:
ResourceBundle.Control კლასს აქვს გარე მეთოდების ნაკრები, რომლებიც გამოიძახება ResourceBundle.getBundle() მეთოდით პაკეტების ძებნისა და ჩატვირთვისას. თქვენი Control კლასის შექმნით, შეგიძლიათ შეცვალოთ ნაგულისხმევი ქცევა ჩატვირთვისა და ქეშისთვის.
ამ შემთხვევაში, თქვენ უნდა შექმნათ Control კლასის ორი მეთოდის იმპლემენტაცია: getFormats() და newBundle(). getFormats() მეთოდი პასუხისმგებელია XML ფორმატის მხარდაჭერაზე, ხოლო newBundle() მუშაობს რესურსების პაკეტთან. კონტროლის საბაზისო კლასში არის დამხმარე მეთოდები საბაზისო ნაკრების სახელების რეალური რესურსების სახელებად გადასაყვანად.
ResourceBundle.Control კლასის ეს განხორციელება მოიცავს XMLResourceBundle-ის ქვეკლასს. ეს ქვეკლასი გამოიყენება XML ფაილიდან მონაცემების ჩასატვირთად და ResourceBundle მეთოდით გამოსაყენებლად.
ქვემოთ მოცემულია Control კლასის აღწერა და ResourceBundle მეთოდის განხორციელება:
იმპორტი java.io.*;
იმპორტი java.net.*;
იმპორტი java.util.*;
საჯარო კლასი XMLResourceBundleControl აფართოებს ResourceBundle.Control (
private static String XML = "xml" ;
საჯარო სიის getFormats(string baseName) (
დაბრუნება Collections.singletonList(XML);
}
Public ResourceBundle newBundle ( სიმებიანი ბაზის სახელი, ლოკალური ლოკალი,
სიმებიანი ფორმატი, ClassLoader loader,ლოგიკური გადატვირთვა)
ისვრის IllegalAccessException, InstantiationException, IOException{
if ((baseName == null) || (locale == null) || (ფორმატი == null)
|| (ჩამტვირთავი == null )) (
გადაყარეთ ახალი NullPointerException ();
}
ResourceBundle bundle = null ;
თუ (ფორმატი. უდრის (XML)) (
სიმებიანი bundleName = toBundleName(ბაზის სახელი, ლოკალი) ;
სიმებიანი რესურსის სახელი = toResourceName(პაკეტის სახელი, ფორმატი) ;
URL url = loader.getResource(რესურსის სახელი);
თუ (url != null) (
URLConnection კავშირი = url.openConnection()
;
თუ (კავშირი != null) (
თუ (გადატვირთვა) (
Connection.setUseCaches(false);
}
InputStream ნაკადი = connection.getInputStream()
;
თუ (ნაკადი != null) (
BufferedInputStream bis = ახალი BufferedInputStream (
ნაკადი);
bundle = new XMLResourceBundle(bis);
bis.close();
}
}
}
}
დაბრუნების შეკვრა;
}
პირადი სტატიკური კლასის XMLResourceBundle აფართოებს ResourceBundle (
private Properties რეკვიზიტები;
XMLResourceBundle (InputStream ნაკადი) აგდებს IOException(
props = new Properties();
props.loadFromXML(stream);
}
დაცული ობიექტი handleGetObject (სტრიქონის გასაღები) (
დაბრუნება props.getProperty(key);
}
საჯარო აღრიცხვა getKeys() (
დააყენეთ handleKeys = props.stringPropertyNames()
;
დაბრუნება Collections.enumeration(handleKeys);
}
}
საჯარო სტატიკური სიცარიელე მთავარი (სტრიქონი არგები) (
("ტესტი 2",
ახალი XMLResourceBundleControl()) ;
სიმებიანი სტრიქონი = bundle.getString("HelpKey");
System.out.println ("HelpKey: " + string );
}
}
ეს განხორციელება მოიცავს სატესტო პროგრამას სამი ხაზისგან:
ResourceBundle bundle = ResourceBundle.getBundle("Test2", ახალი XMLResourceBundleControl()) ;
სიმებიანი სტრიქონი = bundle.getString("HelpKey");
System.out.println ("HelpKey: " + string );
პირველი ხაზი აქ ყველაზე დიდ ინტერესს იწვევს. თქვენ უნდა გადასცეთ თქვენი Control getBundle() მეთოდს. ამის შემდეგ, თქვენ შეგიძლიათ გამოიყენოთ ნაკრები, როგორც ნებისმიერ სხვა შემთხვევაში.
ქვემოთ მოცემულია XML ფაილის მაგალითი Test2.xml:
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
http://java.sun.com/dtd/properties.dtd"
>
XMLResourceBundleControl პროგრამის შესრულების შედეგი იქნება:
> java XMLResourceBundleControl HelpKey: დახმარება
ზემოაღნიშნული განხორციელება არ იყენებს getTimeToLive() და needReload() მეთოდებს:
საჯარო ხანგრძლივი getTimeToLive( სიმებიანი ბაზის სახელი, ლოკალური ლოკალი)
საჯარო ლოგიკური საჭიროებების გადატვირთვა ( სიმებიანი ბაზის სახელი,
ლოკალური ლოკალი,
სიმებიანი ფორმატი
ClassLoader loader
ResourceBundle პაკეტი
ხანგრძლივი დატვირთვის დრო)
getTimeToLive() მეთოდი აბრუნებს რესურსების პაკეტების სიცოცხლეს, რომლებიც შექმნილია ResourceBundle.Control-ის გამოყენებით. რესურსების ნაკრები ინახება ქეშში გადატვირთვის პროცესის დასაჩქარებლად. ამრიგად, როდესაც ნაკრები ხელახლა ჩამოიტვირთება, ის იქნება ქეშში. პოზიტიური დროის არსებობის მნიშვნელობა მილიწამებში განსაზღვრავს, რამდენ ხანს დარჩება ნაკრები ქეშში ხელახლა შემოწმების გარეშე. getTimeToLive() მეთოდით დაბრუნებული ნაგულისხმევი მნიშვნელობა არის TTL_NO_EXPIRATION_CONTROL, რომელიც გამორთავს ქეშის ვადის გასვლის შემოწმებას. თუ არ გსურთ ნაკრების ქეშირება, მაშინ დააბრუნეთ მნიშვნელობა TTL_DONT_CACHE. თუ 0 დაბრუნდა, პაკეტი შეინახება ქეშით, მაგრამ ის მოწმდება ყოველ ჯერზე, როცა getBundle() გამოიძახება. ქეშის გასასუფთავებლად გამოიძახეთ ResourceBundle კლასის სტატიკური clearCache() მეთოდი. მას აქვს არჩევითი ClassLoader არგუმენტი, რომელიც საშუალებას გაძლევთ გაასუფთავოთ კონკრეტული ჩამტვირთველის მიერ შექმნილი ქეშები.
needReload() მეთოდი განსაზღვრავს, უნდა ჩაიტვირთოს თუ არა ქეშირებული ნაკრები. მნიშვნელობა true ნიშნავს, რომ კომპლექტს ხელახლა ჩატვირთვა სჭირდება, ხოლო false ნიშნავს, რომ არ საჭიროებს გადატვირთვას. თქვენ შეგიძლიათ აკონტროლოთ საჭიროებს თუ არა რესურსების ნაკრების გადატვირთვას needReload() მეთოდის გადატვირთვით. მაგალითად, თუ გსურთ, რომ რესურსის ნაკრები ყოველთვის იყოს გადატვირთული, needReload() მეთოდი ყოველთვის უნდა დააბრუნოს true. ამ შემთხვევაში, getTimeToLive() მეთოდმა ყოველთვის უნდა დააბრუნოს მნიშვნელობა 0. წინააღმდეგ შემთხვევაში, ნაკრები შეინახება მოსალოდნელზე დიდხანს.
Mustang-ში ინტერნაციონალიზაციის პროცესებთან დაკავშირებული გაუმჯობესებების შესახებ დამატებითი ინფორმაციისთვის შეგიძლიათ ეწვიოთ Sun პროგრამული უზრუნველყოფის შემქმნელის ჯონ ოკონერის ბლოგს, მისამართზე:
ბოლო დროს რესურსების ჩატვირთვის თემა არაერთხელ გაჩნდა. მოკლედ: „ვიტვირთავ სურათს c:\work\image.gif-დან, მაგრამ როცა პროგრამას jar ფაილიდან/სხვა კომპიუტერზე ვატარებ, ის არ იტვირთება. Რა უნდა ვქნა?".
იმავდროულად, აქ არაფერია რთული. თქვენ უბრალოდ უნდა გესმოდეთ პრინციპები.
უპირველეს ყოვლისა, რესურსების დისკზე აბსოლუტურ მისამართზე ჩატვირთვა უშედეგო ვარჯიშია. ვფიქრობ, თქვენ თვითონაც მშვენივრად გესმით, რატომ - ამოიღეთ ფაილი დისკიდან და "მშვიდობით რესურსს". თქვენ უნდა ატაროთ ყველაფერი თქვენთან ერთად.
მეორე ვარიანტი, რომელსაც ხშირად ვხედავ, არის რესურსის ჩატვირთვა jar ფაილიდან. მაგრამ აქ ძალიან ხშირად უშვებენ ერთ შეცდომას - java.io.File კლასის საშუალებით ცდილობენ რესურსის ჩატვირთვას. იმისდა მიუხედავად, რომ ეს კლასი განკუთვნილია მხოლოდ ფაილურ სისტემებთან მუშაობისთვის.
მიუხედავად იმისა, რომ თავად იდეა სწორია. საჭირო რესურსი ნამდვილად უნდა განთავსდეს jar ფაილში. თქვენ უბრალოდ უნდა გესმოდეთ, როგორ გადმოწეროთ იგი იქიდან. სწორედ ამაზე გეტყვით.
რესურსის ჩასატვირთად გამოიყენეთ მეთოდები java.lang.Class.getResource(String), java.lang.Class.getResourceAsStream(Stri ng) , java.lang.ClassLoader.getResource(String) და java.lang.ClassLoader.getResourceAsStrea m (სტრიქონი) . კლასის მეთოდები აწვდის ზარებს ClassLoader-ზე.
რესურსის სახელის მინიჭებული GetResource(String) აბრუნებს java.net.URL-ს, რომლის მეშვეობითაც შესაძლებელია რესურსის მოძიება. getResourceAsStream(String) , როგორც თქვენ ალბათ მიხვდებით, აბრუნებს java.io.InputStream-ს, რომლის საშუალებითაც შესაძლებელია რესურსის წაკითხვა.
რესურსის სახელი არის გზა რესურსისკენ. არსებობს ერთი მნიშვნელოვანი დახვეწილობა, კერძოდ, როგორ არის მისი ინტერპრეტაცია.
სახელი შეიძლება იყოს აბსოლუტური ან ფარდობითი. გარეგანი განსხვავება ისაა, რომ აბსოლუტური სახელი იწყება "/" სიმბოლოთი. პირველ შემთხვევაში, რესურსის ძიება ხდება classpath-ის ფესვთან შედარებით. იმათ. ყველა ბილიკი და jar ფაილი, რომელიც შედის კლასში, აღებულია და რესურსი იძებნება ამ წერტილების მთლიანობასთან შედარებით. თუ სახელი ფარდობითია, დასაწყისში ემატება მიმდინარე კლასის პაკეტიდან მიღებული გზა. შემდეგ ხდება ძებნა, როგორც აბსოლუტური სახელის შემთხვევაში.
ამის გაგება უფრო ადვილია მაგალითებით. მოდით გვქონდეს მოცემული კლასის გზა: c:\work\myproject\classes;c:\lib\lib.jar. მაგალითის კოდი არის ru.skipy.test.ResourceLoadingTest კლასში.
მაგალითი 1. ჩვენ ვიყენებთ getClass().getResource("/images/logo.png") კონსტრუქციას. ვინაიდან სახელი იწყება "/" სიმბოლოთი, იგი აბსოლუტურად ითვლება. რესურსის ძებნა ხდება შემდეგნაირად:
- კლასის გზა c:\work\myproject\classes დართულია რესურსის სახელით /images/logo.png, რის შედეგადაც მოძებნილია ფაილი c:\work\myproject\classes\images\logo.pn g. თუ ფაილი იპოვეს, ძებნა ჩერდება. წინააღმდეგ შემთხვევაში:
- jar ფაილში c:\lib\lib.jar იძებნება ფაილი /images/logo.png და ძიება ხორციელდება jar ფაილის ძირიდან.
- მიმდინარე კლასის პაკეტს, სადაც მდებარეობს კოდი, ენიჭება გზას classpath c:\work\myproject\classes – /ru/skipy/test – და შემდეგ რესურსის სახელი res/data.txt, რის შედეგადაც ფაილი c:\work\ მოძებნილია myproject\classes\ru\skipy\test\r es\data.txt. თუ ფაილი იპოვეს, ძებნა ჩერდება. წინააღმდეგ შემთხვევაში:
- jar ფაილში c:\lib\lib.jar იძებნება ფაილი /ru/skipy/test/res/data.txt (მიმდინარე კლასის პაკეტის სახელი პლუს რესურსის სახელი) და ძიება ხორციელდება jar ფაილის ფესვი.
აქ შეგიძლიათ ჩამოტვირთოთ სრულად სამუშაო მაგალითი, რომელიც ასახავს ორივე ტიპის დატვირთვას: . რესურსები - სურათი და ტექსტი - განლაგებულია ცალკე დირექტორიაში, აწყობის დროს ისინი მთავრდება jar ფაილში და იტვირთება, ერთი აბსოლუტური სახელით, მეორე - ნათესავი სახელით. მაგალითი აგებულია და გაშვებულია ant-ის მეშვეობით, ant run ბრძანებით ის გაშვებულია build/classes/ build დირექტორიადან და ant run-jar ბრძანებით აწყობილი jar ფაილიდან.
აი, სადღაც ასე. კითხვები? კომენტარები?