Silverlight資源文件引用相關難題解析
Silverlight開發工具在進行資源的引用的時候,可能會出現一些問題困擾著開發人員難以將程序進程向前推進。尤其是剛剛接觸這款工具不久的新手來說尤其頭疼。我們在這里就為大家介紹了一下Silverlight資源文件引用的一些相關問題及解決辦法。#t#
Silverlight資源文件引用問題描述
最近項目中遇到一個和資源文件相關的很奇怪的問題。有一個Silverlight應用會根據當前Url中的某個特定參數來決定使用什么文化的資源文件(關于資源的文件的使用見Silverlight 2 RTM 多國語言支持)。在其他機器上運行沒有問題,傳入zh-Hans和en-US界面都能正確顯示相應語言的文字。但是在我的系統上卻不管傳入什么都是顯示的英文文字。
Silverlight資源文件引用問題分析
打開工程看了一下,在資源文件夾下只定義了兩個資源,一個是主資源XXX.resx,一個是英文中立資源XXX.en.resx。編譯之后,主資源會被打包到主程序集中,而其他資源則被編譯成獨立的程序集,稱為衛星程序集。Silverlight代碼中在提取Url參數的時候也加上了一個檢測邏輯,就是如果傳入的語言不是英文,那么就使用zh-Hans。也就是說在其他人的機器上,如果你輸入了fr,那么也是顯示中文。分析加調試弄了好一會之后,我判定應該不是程序代碼的bug。因為在某些人的機器上是正常的,而在我的機器還有另外一個同事的機器上卻不正常,而且問題是可重現的。這說明了問題和本地環境有關。
清緩存,清Silverlight獨立存儲之后發現問題依然存在。難道是操作系統的問題?!我用的是win7,同事用的是win2008,都是高版本的windows,而其他人用的不是xp就是2003。為了證實我的想法,我又找了一臺2008的機器,測試結果和我機器上的一樣。看來很有可能問題就在這。可是,為什么呢?
為了查找問題的原因,我重新查閱了一下Silverlight使用資源文件的相關材料(和DotNet其實差不多)。
Silverlight資源文件引用的查找方式
Silverlight采用中心輻射型結構來打包和部署資源文件程序集。圍繞在中心的是主程序集里面的資源,這個資源也被稱為中立或者默認資源。如果主程序集沒有顯式設定語言,那么一個資源要是查找失敗,最終會使用主程序集中的資源。每個輻射點指向的是每一種語言對應的衛星程序集。
Silverlight在查找資源文件的時候采用了如下的方式:
最***是應用程序的默認程序集。第二級是語言相關程序集,它代表的是地域無關的語言文化,如英文,簡體中文,繁體中文(zh-Hant)等;第三級是和地域相關的文化程序集,如美國英語,英國英語,大陸簡體中文,新加坡簡體中文。Silverlight在加載本地資源的時候首先會根據CultureInfo.CurrentUICulture屬性來判斷應該加載哪一種文化對應的資源。在查找的時候是按照上面的層次結構從下到上進行查找的。具體說來,當ResourceManager在查找一個資源時會經過以下幾個步驟:
1. 查找具體語言相應的程序集是否存在。如設置了zh-CN,那么就查找XXX.zh-CN.resx資源文件是否存在(存在于衛星程序集中),如果程序集不存在或者在該程序集中找不到此資源的定義,那么查找失敗。如果操作系統支持回溯(Fallback)邏輯,那么跳到第二步;否則跳到第三步。
2. 操作系統提供一份推薦的語言回溯清單,上面包含了具體語言文化字符串(如en-US)和相應的中立語言字符串(如en)。Resource Manager會根據這份清單去查找相應的衛星程序集和程序集內指定資源是否存在。如果查找失敗,則跳到下一步。
3. 如果上面兩步都失敗,那么查找此具體文化的上一級文化的衛星程序集,也就是地域無關的文化,例如en-US查找失敗,則查找en是否存在。
4. 如果上面3步都失敗的話,那么Silverlight會查看主程序集的NeutralResourcesLanguageAttribute屬性。NeutralResourcesLanguageAttribute是用在程序集上的屬性,它是用來告知ResourceManager,某個程序集使用的語言是什么。ResourceManager會查看此屬性的值,看是否滿足條件。如果主程序集沒有指定此屬性,那么將會使用主程序集中的資源作為默認資源。
5. 如果第4步也查找失敗,那么ResourceManager將使用文化無關(Invarient Culture)的資源。
Silverlight資源文件引用問題所在
在網上查到MSDN的文章說,自打Vista開始,操作系統開始支持這種“Fallback”的邏輯了。通過系統API GetThreadPreferredUILanguages可以獲取操作系統核心推薦使用的語言清單。
由于工程里面并沒有指定zh-Hans的資源文件(于是也就沒有zh-Hans的衛星程序集),也沒有設置主程序集使用的語言是什么(通過NeutralResourcesLanguageAttribute屬性指定)因此在***步的時候查找失敗;這個時候,在我win7的機器上,由于操作系統支持fallback邏輯,因此Silverlight會使用操作系統提供的語言清單去查找,由于我的系統是中文系統,因此清單上***項肯定是zh-CN,接下來的猜測應該是en-US和en(老美搞的操作系統嘛,當然要把自家語言排前一點了)。查找zh-CN肯定又失敗,但是查找en卻能夠找到,因此就出現了不管你參數中輸入什么語言文化字符串,都會顯示英文。
而在其他低版本的windows上,因為操作系統不支持這份清單,那么Silverlight始終沒有辦法找到zh-Hans相關的衛星程序集,而主程序集又沒有顯式的設置語言,因此ResourceManager就會使用主程序集里面的資源文件,也就是中文。
這就是為什么在低版本windows上,亂輸入語言,顯示的默認是中文,而在Vista等高版本windows上,默認顯示的是英文的緣故。
再插一句,如果在主程序集中顯式設置了NeutralResourcesLanguageAttribute為zh-Hans,然后在低版本的windows上訪問此應用程序的時候輸入例如fr等不支持的語言,那么Silverlight將會使用語言無關的資源(語言無關的資源具體被定義在哪不是很確定,可能是dotnet類庫,也可能是本地操作系統),如果該語言無關的資源沒有定義,則ResourceManager得到的是空字符串。因為此時ResourceManager就不會把主程序集里的資源當作最終Fallback的資源了。
解決Silverlight資源文件引用問題的辦法
經過上面的分析,解決問題的辦法已經很清楚了,要么再添加一個zh-Hans的資源文件,要么顯式的使用NeutralResourcesLanguageAttribute通知ResourceManager,主程序集使用的資源語言是zh-Hans。