[原]ASP.NET MVC 3 Razor多言語リファレンスソリューション補足

5721 ワード

ところで、張骨董品は妻を李成龍に貸したが、結局借りられなかった.このことはどちらもおかしい:張骨董品の動機は純粋ではなく、李成龍は人を作るのも厚かましくないが、一般的には人を安くするのは中毒だ.
Reflector知らない人はいないでしょう.NETは何年も使っている人はもう見に行く必要はないかもしれません.NETソースコードは、一つは前に見たことがありますが、二つ目は多くの実現方法と運行原理が推測できますが、初心者や見たい人にはよくありません.NETタイプのソースコードの人にとって、Reflectorがないのはつらいです.しかし先日突然ニュースを闻いて、Reflectorは意外にも有料になりました!!!こんな使いやすいツールを、無料で使わないなんて???これはまるで張骨董品が妻を李成龍に貸したように、李成龍に夜夜笙歌を歌わせた.しかしReflectorは死んだもので、あなたはどんなに呼んでも主人の命令に従わなければなりません.また遠ざかった...
本題に入る:
前文において、Systemが使用する.Resources.ResXResourceReader(System.Windows.Forms.dll)タイプはリソースファイルのアイテムを取得する方法でMVC下のLocalizationを実現しましたが、このシナリオはプロトタイプか参考シナリオとしか言えません.今日またこのタイプを検討しましたが、同僚の手元に昇格していないReflectorがいてよかったのです(自動アップグレードボタンをうっかり注文しましたが、これは権利侵害ではないでしょう).ResXResourceReaderの実現原理を見てみると、このタイプは解析XMLを使ってリソース項目を取り出し、IDictionaryEnumeratorの中に入れたものだった.
このようにして、このタイプはWebプログラムの中で安全に使用することができます.このタイプの主なオーバーヘッドはresxファイルの読み取りと解析にあります.普段はキャッシュを使ってパフォーマンスの問題を解決するのが好きですが、今回は例外ではありません.NET 4からSystemが出る.Runtime.Caching.MemoryCacheはまだ使ったことがないので、手の練習に出しました.
piapiaの場合、上記のコードを以下のように変更します.
    public static class LocalizationHelpers

    {

        public static string Lang(this HtmlHelper htmlhelper, string key)

        {

            var viewPath = (htmlhelper.ViewContext.View as BuildManagerCompiledView).ViewPath;

            var viewName = viewPath.Substring(viewPath.LastIndexOf('/'), viewPath.Length - viewPath.LastIndexOf('/')).TrimStart('/');

            var filePath = htmlhelper.ViewContext.HttpContext.Server.MapPath(viewPath.Substring(0, viewPath.LastIndexOf('/') + 1)) + "App_LocalResources";

            var langs = htmlhelper.ViewContext.HttpContext.Request.UserLanguages;



            string resxPath = string.Format(@"{0}\{1}.resx", filePath, viewName);



            foreach (var lang in langs)

            {

                if (File.Exists(string.Format(@"{0}\{1}.{2}.resx", filePath, viewName, lang)))

                {

                    resxPath = string.Format(@"{0}\{1}.{2}.resx", filePath, viewName, lang);

                    break;

                }

            }



            var result = ResXCache.GetResValue(resxPath, key);



            return result;

        }



        public static class ResXCache

        {

            public static string GetResValue(string file, string key)

            {

                ObjectCache cache = MemoryCache.Default;



                IEnumerable<DictionaryEntry> resxs = null;



                if (cache.Contains(file) == false)

                {

                    resxs = new ResXResourceReader(file).Cast<DictionaryEntry>();

                    cache.Add(file, resxs, new CacheItemPolicy() { Priority = CacheItemPriority.NotRemovable });

                }

                else

                {

                    resxs = cache.GetCacheItem(file).Value as IEnumerable<DictionaryEntry>;

                }



                return (string)resxs.FirstOrDefault<DictionaryEntry>(x => x.Key.ToString() == key).Value;

            }

        }

    }


OK、基本的にこの案はプロジェクトに使えると思います.
3月19日に内容を更新し、Langメソッドを書き換え、リソースファイルが存在するかどうかを検証する手順を減らした-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    public static class LocalizationHelper

    {

        public static string Lang(this HtmlHelper htmlhelper, string key)

        {

            var viewPath = (htmlhelper.ViewContext.View as BuildManagerCompiledView).ViewPath;

            var viewName = viewPath.Substring(viewPath.LastIndexOf('/'), viewPath.Length - viewPath.LastIndexOf('/')).TrimStart('/');

            var filePath = htmlhelper.ViewContext.HttpContext.Server.MapPath(viewPath.Substring(0, viewPath.LastIndexOf('/') + 1)) + "App_LocalResources";

            var langs = htmlhelper.ViewContext.HttpContext.Request.UserLanguages.Union<string>(new string[] { "" });



            IEnumerable<DictionaryEntry> resxs = null;



            foreach (var lang in langs)

            {

                var resxKey =

                    string.IsNullOrWhiteSpace(lang) ? string.Format(@"{0}\{1}.resx", filePath, viewName) : string.Format(@"{0}\{1}.{2}.resx", filePath, viewName, lang);



                resxs = GetResx(resxKey);



                if (resxs != null) { break; }

            }



            return (string)resxs.FirstOrDefault<DictionaryEntry>(x => x.Key.ToString() == key).Value;

        }



        private static IEnumerable<DictionaryEntry> GetResx(string resxKey)

        {

            ObjectCache cache = MemoryCache.Default;



            IEnumerable<DictionaryEntry> resxs = null;



            if (cache.Contains(resxKey))

            {

                resxs = cache.GetCacheItem(resxKey).Value as IEnumerable<DictionaryEntry>;

            }

            else

            {

                if (File.Exists(resxKey))

                {

                    resxs = new ResXResourceReader(resxKey).Cast<DictionaryEntry>();

                    cache.Add(resxKey, resxs, new CacheItemPolicy() { Priority = CacheItemPriority.NotRemovable });

                }

            }



            return resxs;

        }

    }