/// <summary> /// Given a visible <paramref name="id"/>, return the display name in the requested <paramref name="locale"/>. /// If there is no directly supported id corresponding to this id, return /// null. /// </summary> public virtual string GetDisplayName(string id, UCultureInfo locale) { IDictionary <string, IServiceFactory> m = GetVisibleIDMap(); if (m.TryGetValue(id, out IServiceFactory f) && f != null) { return(f.GetDisplayName(id, locale)); } ICUServiceKey key = CreateKey(id); while (key.Fallback()) { if (m.TryGetValue(key.CurrentID, out f) && f != null) { return(f.GetDisplayName(id, locale)); } } return(null); }
/// <summary> /// Given a visible <paramref name="id"/>, return the display name in the requested <paramref name="locale"/>. /// If there is no directly supported id corresponding to this id, return /// null. /// </summary> public virtual string GetDisplayName(string id, ULocale locale) { IDictionary <string, IServiceFactory> m = GetVisibleIDMap(); IServiceFactory f = m.Get(id); if (f != null) { return(f.GetDisplayName(id, locale)); } ICUServiceKey key = CreateKey(id); while (key.Fallback()) { f = m.Get(key.CurrentID); if (f != null) { return(f.GetDisplayName(id, locale)); } } return(null); }
private CacheEntry GetKeyCacheEntry(ICUServiceKey key, IServiceFactory factory) { if (DEBUG) { Console.Out.WriteLine("Service: " + m_name + " key: " + key.CanonicalID); } if (key != null) { try { // The factory list can't be modified until we're done, // otherwise we might update the cache with an invalid result. // The cache has to stay in synch with the factory list. factoryLock.AcquireRead(); IDictionary <string, CacheEntry> cache = this.cache; // copy so we don't need to sync on this if (cache == null) { if (DEBUG) { Console.Out.WriteLine("Service " + m_name + " cache was empty"); } // synchronized since additions and queries on the cache must be atomic // they can be interleaved, though cache = new ConcurrentDictionary <string, CacheEntry>(); } string currentDescriptor = null; List <string> cacheDescriptorList = null; bool putInCache = false; int NDebug = 0; int startIndex = 0; int limit = factories.Count; bool cacheResult = true; if (factory != null) { for (int i = 0; i < limit; ++i) { if (factory == factories[i]) { startIndex = i + 1; break; } } if (startIndex == 0) { throw new InvalidOperationException("Factory " + factory + "not registered with service: " + this); } cacheResult = false; } CacheEntry result; //outer: do { currentDescriptor = key.GetCurrentDescriptor(); if (DEBUG) { Console.Out.WriteLine(m_name + "[" + NDebug++ + "] looking for: " + currentDescriptor); } if (cache.TryGetValue(currentDescriptor, out result) && result != null) { if (DEBUG) { Console.Out.WriteLine(m_name + " found with descriptor: " + currentDescriptor); } goto outer_break; } else { if (DEBUG) { Console.Out.WriteLine("did not find: " + currentDescriptor + " in cache"); } } // first test of cache failed, so we'll have to update // the cache if we eventually succeed-- that is, if we're // going to update the cache at all. putInCache = cacheResult; // int n = 0; int index = startIndex; while (index < limit) { IServiceFactory f = factories[index++]; if (DEBUG) { Console.Out.WriteLine("trying factory[" + (index - 1) + "] " + f.ToString()); } object service = f.Create(key, this); if (service != null) { result = new CacheEntry(currentDescriptor, service); if (DEBUG) { Console.Out.WriteLine(m_name + " factory supported: " + currentDescriptor + ", caching"); } goto outer_break; } else { if (DEBUG) { Console.Out.WriteLine("factory did not support: " + currentDescriptor); } } } // prepare to load the cache with all additional ids that // will resolve to result, assuming we'll succeed. We // don't want to keep querying on an id that's going to // fallback to the one that succeeded, we want to hit the // cache the first time next goaround. if (cacheDescriptorList == null) { cacheDescriptorList = new List <string>(5); } cacheDescriptorList.Add(currentDescriptor); } while (key.Fallback()); outer_break : { } if (result != null) { if (putInCache) { if (DEBUG) { Console.Out.WriteLine("caching '" + result.actualDescriptor + "'"); } cache[result.actualDescriptor] = result; if (cacheDescriptorList != null) { foreach (string desc in cacheDescriptorList) { if (DEBUG) { Console.Out.WriteLine(m_name + " adding descriptor: '" + desc + "' for actual: '" + result.actualDescriptor + "'"); } cache[desc] = result; } } // Atomic update. We held the read lock all this time // so we know our cache is consistent with the factory list. // We might stomp over a cache that some other thread // rebuilt, but that's the breaks. They're both good. this.cache = cache; } if (DEBUG) { Console.Out.WriteLine("found in service: " + m_name); } return(result); } } finally { factoryLock.ReleaseRead(); } } if (DEBUG) { Console.Out.WriteLine("not found in service: " + m_name); } return(null); }