/// <summary> /// Log resource resolve /// </summary> /// <param name="value"></param> public void OnNext(LineResourceBytes value) { // Get reference var _logger = Logger(value.Line); // Is disposed? if (_logger == null) { return; } // Get severity LineStatusSeverity severity = value.Severity; // Write status if (_logger.IsEnabled(LogLevel.Trace) && severity == LineStatusSeverity.Ok) { _logger.LogInformation(value.Exception, value.DebugInfo); return; } if (_logger.IsEnabled(LogLevel.Warning) && severity == LineStatusSeverity.Warning) { _logger.LogWarning(value.Exception, value.DebugInfo); return; } if (_logger.IsEnabled(LogLevel.Error) && severity >= LineStatusSeverity.Error) { _logger.LogError(value.Exception, value.DebugInfo); return; } }
/// <summary> /// Log byte resolve /// </summary> /// <param name="value"></param> public void OnNext(LineResourceBytes value) { // Get reference var _logger = logger; // Is disposed? if (_logger == null) { return; } // Get severity LineStatusSeverity severity = value.Severity; // Severity under threshold? if (severity < this.severity) { return; } // Write status if (value.Exception == null) { _logger.WriteLine(value.DebugInfo); } else { _logger.WriteLine("{0} {1}: {2}", value.DebugInfo, value.Exception.GetType().Name, value.Exception.Message); } }
/// <summary> /// Resolve <paramref name="line"/> into bytes. /// /// Applies contextual information, such as culture, from the executing context. /// executing context. /// /// Status codes: /// <list type="bullet"> /// <item><see cref="LineStatus.ResolveOkFromAsset"/>Resource was acquired</item> /// <item><see cref="LineStatus.ResolveOkFromInline"/>Resource was acquired</item> /// <item><see cref="LineStatus.ResolveOkFromLine"/>Resource was acquired</item> /// <item><see cref="LineStatus.ResolveFailedNoValue"/>If resource could not be found</item> /// <item><see cref="LineStatus.ResolveFailedNoResult"/>Request was not processed</item> /// <item><see cref="LineStatus.ResolveFailedException"/>Unexpected exception was thrown, <see cref="LineResourceBytes.Exception"/></item> /// <item><see cref="LineStatus.ResolveFailedNoResourceResolver"/>Resolver was not found.</item> /// </list> /// </summary> /// <param name="line"></param> /// <returns>result status</returns> public static LineResourceBytes ResolveBytes(this ILine line) { LineResourceBytes result = new LineResourceBytes(line, (Exception)null, LineStatus.ResolveFailedNoResourceResolver); for (ILine k = line; k != null; k = k.GetPreviousPart()) { IResourceResolver resolver; if (k is ILineResourceResolver resolverAssigned && ((resolver = resolverAssigned.ResourceResolver) != null)) { LineResourceBytes str = resolver.ResolveBytes(line); // Return bytes if (str.Value != null) { return(str); } // Got better code, move on if (str.Severity <= result.Severity) { result = str; } } } return(result); }
/// <summary> /// Log string /// </summary> /// <param name="value"></param> public void OnNext(LineResourceBytes value) { // Get reference var _logger = logger; // Is disposed? if (_logger == null) { return; } // Get severity LineStatusSeverity severity = value.Severity; // Write status if (severity == LineStatusSeverity.Ok && _logger.IsInfoEnabled) { _logger.Info(value.Exception, value.DebugInfo); return; } if (severity == LineStatusSeverity.Warning && _logger.IsWarnEnabled) { _logger.Warn(value.Exception, value.DebugInfo); return; } if (severity >= LineStatusSeverity.Error && _logger.IsErrorEnabled) { _logger.Error(value.Exception, value.DebugInfo); return; } }
/// <summary> /// Try to read a binary resource by matching <paramref name="key"/> to the asset's resources /// /// Does not apply contextual information from the executing context. (See <see cref="ILineExtensions.ResolveBytes(ILine)"/> to match in context.) /// /// Status codes: /// <list type="bullet"> /// <item><see cref="LineStatus.ResolveOkFromAsset"/>Resource was acquired</item> /// <item><see cref="LineStatus.ResolveOkFromInline"/>Resource was acquired</item> /// <item><see cref="LineStatus.ResolveOkFromLine"/>Resource was acquired</item> /// <item><see cref="LineStatus.ResolveFailedNoValue"/>If resource could not be found</item> /// <item><see cref="LineStatus.ResolveFailedNoResult"/>Request was not processed</item> /// <item><see cref="LineStatus.ResolveFailedException"/>Unexpected exception was thrown, <see cref="LineResourceBytes.Exception"/></item> /// </list> /// </summary> /// <param name="asset"></param> /// <param name="key"></param> /// <returns>result info</returns> public static LineResourceBytes GetResourceBytes(this IAsset asset, ILine key) { if (asset is IResourceAsset casted) { LineResourceBytes data = casted.GetResourceBytes(key); if (data.Value != null) { return(data); } } if (asset is IAssetComposition composition) { foreach (IResourceAsset component in composition.GetComponents <IResourceAsset>(true) ?? Enumerable.Empty <IResourceAsset>()) { LineResourceBytes data = component.GetResourceBytes(key); if (data.Value != null) { return(data); } } foreach (IAssetProvider component in composition.GetComponents <IAssetProvider>(true) ?? Enumerable.Empty <IAssetProvider>()) { IEnumerable <IAsset> assets = component.LoadAssets(key); if (assets != null) { foreach (IAsset loaded_asset in assets) { LineResourceBytes data = loaded_asset.GetResourceBytes(key); if (data.Value != null) { return(data); } } } } } if (asset is IAssetProvider provider) { IEnumerable <IAsset> assets = provider.LoadAssets(key); if (assets != null) { foreach (IAsset loaded_asset in assets) { LineResourceBytes data = loaded_asset.GetResourceBytes(key); if (data.Value != null) { return(data); } } } } // No result return(new LineResourceBytes(key, (Exception)null, LineStatus.ResolveFailedNoResult)); }
/// <summary> /// Log resource resolve /// </summary> /// <param name="value"></param> public void OnNext(LineResourceBytes value) { if (disposed) { return; } // Get severity LineStatusSeverity severity = value.Severity; // Threshold if (severity < this.severity) { return; } // Write status if (value.Exception == null) { // No exception switch (severity) { case LineStatusSeverity.Ok: Trace.TraceInformation(value.DebugInfo); return; case LineStatusSeverity.Warning: Trace.TraceWarning(value.DebugInfo); return; case LineStatusSeverity.Error: case LineStatusSeverity.Failed: Trace.TraceError(value.DebugInfo); return; } } else { // With exception switch (severity) { case LineStatusSeverity.Ok: Trace.TraceInformation("{0} {1}: {2}", value.DebugInfo, value.Exception.GetType().Name, value.Exception); return; case LineStatusSeverity.Warning: Trace.TraceWarning("{0} {1}: {2}", value.DebugInfo, value.Exception.GetType().Name, value.Exception); return; case LineStatusSeverity.Error: case LineStatusSeverity.Failed: Trace.TraceError("{0} {1}: {2}", value.DebugInfo, value.Exception.GetType().Name, value.Exception); return; } } }
/// <summary> /// Get resource /// </summary> /// <param name="key"></param> /// <returns></returns> public LineResourceBytes GetResourceBytes(ILine key) { Cache _cache = this.cache; // Try to read previously cached value LineResourceBytes value = default; _cache.m_lock.EnterReadLock(); try { if (_cache.data.TryGetValue(key, out value)) { return(value); } } finally { _cache.m_lock.ExitReadLock(); } // Read from backend and write to cache value = Source.GetResourceBytes(key); // Write to cache, be that null or not if (value.Value != null && value.Value.Length <= Options.GetMaxResourceSize()) { ILine cacheKey = key.CloneKey(LineAppender.NonResolving); _cache.m_lock.EnterWriteLock(); try { _cache.data[cacheKey] = value; } finally { _cache.m_lock.ExitWriteLock(); } } return(value); }
public static void Main(string[] args) { // 1. Line { #region Snippet_1a ILine key = LineRoot.Global.PluralRules("Unicode.CLDR35").Key("Key").Format("Hello, {0}"); #endregion Snippet_1a } { #region Snippet_1b ILineRoot root = new LineRoot(); ILine hint1 = root.PluralRules("Unicode.CLDR35"); ILine section1 = hint1.Section("Section2"); ILine section1_1 = hint1.Section("Section1.1"); ILine key1_1_1 = section1_1.Key("Key1"); ILine key1_1_2 = section1_1.Key("Key2"); ILine value1_1_1 = key1_1_1.Format("Hello, {0}"); // ... #endregion Snippet_1b } // 2. Parts { #region Snippet_2a IAsset resourceAsset = new ResourceDictionary(new Dictionary <ILine, byte[]>()); ILine line = LineRoot.Global.Asset(resourceAsset); #endregion Snippet_2a } { #region Snippet_2b ILine line = LineRoot.Global.Logger(Console.Out, LineStatusSeverity.Ok); #endregion Snippet_2b } { #region Snippet_2c ICulturePolicy culturePolicy = new CulturePolicy().SetToCurrentCulture(); ILine line = LineRoot.Global.CulturePolicy(culturePolicy); #endregion Snippet_2c } { #region Snippet_2d #endregion Snippet_2d } { #region Snippet_2e #endregion Snippet_2e } { #region Snippet_2f #endregion Snippet_2f } { #region Snippet_2g #endregion Snippet_2g } { #region Snippet_2h #endregion Snippet_2h } // 3. Hints { #region Snippet_3_ IAsset asset = LineReaderMap.Default.FileAsset("ILine\\Hints.ini"); ILineRoot root = new LineRoot(asset); Console.WriteLine(root.Key("Error").Value(DateTime.Now)); Console.WriteLine(root.Key("Ok")); #endregion Snippet_3_ } { #region Snippet_3a ILine line1 = LineRoot.Global.StringFormat(TextFormat.Default).String("Text"); ILine line2 = LineRoot.Global.StringFormat("Lexical.Localization.StringFormat.TextFormat,Lexical.Localization") .String("Text"); #endregion Snippet_3a Console.WriteLine(line2); } { #region Snippet_3b IPluralRules pluralRules = PluralRulesResolver.Default.Resolve("Unicode.CLDR35"); ILine line1 = LineRoot.Global.PluralRules(pluralRules); ILine line2 = LineRoot.Global.PluralRules("Unicode.CLDR35"); ILine line3 = LineRoot.Global.PluralRules("[Category=cardinal,Case=one]n=1[Category=cardinal,Case=other]true"); #endregion Snippet_3b Console.WriteLine(line2); } { #region Snippet_3c IFormatProvider customFormat = new CustomFormat(); ILine line1 = LineRoot.Global.FormatProvider(customFormat).Format("{0:DATE}").Value(DateTime.Now); ILine line2 = LineRoot.Global.FormatProvider("docs.CustomFormat,docs").Format("{0:DATE}").Value(DateTime.Now); #endregion Snippet_3c Console.WriteLine(line1); Console.WriteLine(line2); } { #region Snippet_3e ResolveSource[] resolveSequence = new ResolveSource[] { ResolveSource.Inline, ResolveSource.Asset, ResolveSource.Line }; IStringResolver stringResolver = new StringResolver(Resolvers.Default, resolveSequence); ILine line = LineRoot.Global.StringResolver(stringResolver); #endregion Snippet_3e Console.WriteLine(line); } { #region Snippet_3f ILine line = LineRoot.Global.StringResolver("Lexical.Localization.StringFormat.StringResolver"); #endregion Snippet_3f Console.WriteLine(line); } { #region Snippet_3g ResolveSource[] resolveSequence = new ResolveSource[] { ResolveSource.Inline, ResolveSource.Asset, ResolveSource.Line }; IResourceResolver resourceResolver = new ResourceResolver(Resolvers.Default, resolveSequence); ILine line = LineRoot.Global.ResourceResolver(resourceResolver); #endregion Snippet_3g Console.WriteLine(line); } { #region Snippet_3h ILine line = LineRoot.Global.ResourceResolver("Lexical.Localization.Resource.ResourceResolver"); #endregion Snippet_3h Console.WriteLine(line); } // 4. Keys { #region Snippet_4a #endregion Snippet_4a } { #region Snippet_4b #endregion Snippet_4b } { #region Snippet_4c #endregion Snippet_4c } { #region Snippet_4d #endregion Snippet_4d } { #region Snippet_4e #endregion Snippet_4e } { #region Snippet_4f #endregion Snippet_4f } { #region Snippet_4g #endregion Snippet_4g } { #region Snippet_4h #endregion Snippet_4h } // 5. Non-canonicals { #region Snippet_5a Assembly asm = typeof(ILine_Examples).Assembly; ILine line1 = LineRoot.Global.Assembly(asm); ILine line2 = LineRoot.Global.Assembly("docs"); #endregion Snippet_5a } { #region Snippet_5b CultureInfo culture = CultureInfo.GetCultureInfo("en"); ILine line1 = LineRoot.Global.Culture(culture); ILine line2 = LineRoot.Global.Culture("en"); #endregion Snippet_5b } { #region Snippet_5c ILine line1 = LineRoot.Global.Type <ILine_Examples>(); ILine line2 = LineRoot.Global.Type(typeof(ILine_Examples)); #endregion Snippet_5c } { #region Snippet_5d #endregion Snippet_5d } { #region Snippet_5e #endregion Snippet_5e } { #region Snippet_5f #endregion Snippet_5f } { #region Snippet_5g #endregion Snippet_5g } { #region Snippet_5h #endregion Snippet_5h } // 6. Canonicals { #region Snippet_6a ILine line = LineRoot.Global.Key("Ok"); #endregion Snippet_6a } { #region Snippet_6b ILine line = LineRoot.Global.Section("Resources").Key("Ok"); #endregion Snippet_6b } { #region Snippet_6c ILine line = LineRoot.Global.Location(@"c:\dir"); #endregion Snippet_6c } { #region Snippet_6d ILine line = LineRoot.Global.BaseName("docs.Resources"); #endregion Snippet_6d } { #region Snippet_6e #endregion Snippet_6e } { #region Snippet_6f #endregion Snippet_6f } { #region Snippet_6g #endregion Snippet_6g } { #region Snippet_6h #endregion Snippet_6h } // 7. Strings { #region Snippet_7a IString str = CSharpFormat.Default.Parse("ErrorCode = 0x{0:X8}"); ILine line = LineRoot.Global.Key("Error").String(str); #endregion Snippet_7a } { #region Snippet_7b ILine line = LineRoot.Global.Key("Error").StringFormat(CSharpFormat.Default).String("ErrorCode = 0x{0:X8}"); #endregion Snippet_7b } { #region Snippet_7c ILine line = LineRoot.Global.Key("Error").Format("ErrorCode = 0x{0:X8}"); #endregion Snippet_7c } { #region Snippet_7c2 int code = 0x100; ILine line = LineRoot.Global.Key("Error").Format($"ErrorCode = 0x{code:X8}"); #endregion Snippet_7c2 Console.WriteLine(line); } { #region Snippet_7d ILine line = LineRoot.Global.Key("Hello").Text("Hello World"); #endregion Snippet_7d } { #region Snippet_7e ILine line = LineRoot.Global.Section("Section").Key("Success") .Format("Success") // Add inlining to the root culture "" .Inline("Culture:en", "Success") // Add inlining to culture "en" .Inline("Culture:fi", "Onnistui") // Add inlining to culture "fi" .Inline("Culture:sv", "Det funkar"); // Add inlining to culture "sv" #endregion Snippet_7e } { #region Snippet_7f ILine line = LineRoot.Global.Section("Section").Key("Success") .Format("Success") // Add inlining to the root culture "" .en("Success") // Add inlining to culture "en" .fi("Onnistui") // Add inlining to culture "fi" .sv("Det funkar"); // Add inlining to culture "sv" #endregion Snippet_7f } // Enumerations { #region Snippet_7l ILine carFeature = LineRoot.Global.Assembly("docs").Type <CarFeature>().Format("{0}"); #endregion Snippet_7l } { #region Snippet_7l2 ILine carFeature = LineRoot.Global.Assembly("docs").Type <CarFeature>().InlineEnum <CarFeature>().Format("{0}"); #endregion Snippet_7l2 } { #region Snippet_7l3 IAssetSource assetSource = LineReaderMap.Default.FileAssetSource(@"ILine\CarFeature.ini"); LineRoot.Builder.AddSource(assetSource).Build(); #endregion Snippet_7l3 } { #region Snippet_7m ILine carFeature = LineRoot.Global.Assembly("docs").Type <CarFeature>() .InlineEnum <CarFeature>() .InlineEnum(CarFeature.Electric, "fi", "Sähkö") .InlineEnum(CarFeature.Petrol, "fi", "Bensiini") .InlineEnum(CarFeature.NaturalGas, "fi", "Maakaasu") .InlineEnum(CarFeature.TwoDoors, "fi", "Kaksiovinen") .InlineEnum(CarFeature.FourDoors, "fi", "Neliovinen") .InlineEnum(CarFeature.FiveDoors, "fi", "Viisiovinen") .InlineEnum(CarFeature.Red, "fi", "Punainen") .InlineEnum(CarFeature.Black, "fi", "Musta") .InlineEnum(CarFeature.White, "fi", "Valkoinen") .Format("{0}"); #endregion Snippet_7m CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(""); #region Snippet_7m2 Console.WriteLine(carFeature.Key(CarFeature.Petrol)); Console.WriteLine(carFeature.Key(CarFeature.Petrol).Culture("fi")); Console.WriteLine(carFeature.Key(CarFeature.Petrol).Culture("sv")); #endregion Snippet_7m2 #region Snippet_7m3 CarFeature features = CarFeature.Petrol | CarFeature.FiveDoors | CarFeature.Black; Console.WriteLine(carFeature.Value(features)); #endregion Snippet_7m3 #region Snippet_7m5 Console.WriteLine(carFeature.Formulate($"{CarFeature.Petrol | CarFeature.Black:|}").Culture("fi")); Console.WriteLine(carFeature.Formulate($"{CarFeature.Petrol | CarFeature.Black: |}").Culture("fi")); #endregion Snippet_7m5 } { #region Snippet_7m6 ILine carFeature = LineRoot.Global.Assembly("docs").Type <CarFeature>().InlineEnum <CarFeature>() .InlineEnum(CarFeature.Electric, "de", "Elektroauto") .InlineEnum(CarFeature.Petrol, "de", "Benzinwagen") .InlineEnum(CarFeature.NaturalGas, "de", "Erdgasauto") .InlineEnum(CarFeature.TwoDoors, "de", "Zweitürig") .InlineEnum(CarFeature.FourDoors, "de", "Viertürig") .InlineEnum(CarFeature.FiveDoors, "de", "Fünftürige") .InlineEnum(CarFeature.Red, "de", "Rot") .InlineEnum(CarFeature.Black, "de", "Schwartz") .InlineEnum(CarFeature.White, "de", "Weiß") .Format("{0}"); ILine message = LineRoot.Global.Assembly("docs").Type("MyClass").Key("Msg") .Format("Your car has following features: {0}") .de("Ihr Auto hat folgende Eigenschaften: {0}"); Console.WriteLine(message.Value(CarFeature.Petrol | CarFeature.Red | CarFeature.TwoDoors).Culture("fi")); Console.WriteLine(message.Value(CarFeature.Petrol | CarFeature.Red | CarFeature.TwoDoors).Culture("sv")); Console.WriteLine(message.Value(CarFeature.Petrol | CarFeature.Red | CarFeature.TwoDoors).Culture("de")); #endregion Snippet_7m6 } { #region Snippet_7m7 ILine carFeature = LineRoot.Global.Assembly("docs").Type <CarFeature>().InlineEnum <CarFeature>() .InlineEnum(CarFeature.Electric, "de", "Elektroauto") .InlineEnum(CarFeature.Petrol, "de", "Benzinwagen") .InlineEnum(CarFeature.NaturalGas, "de", "Erdgasauto") .InlineEnum(CarFeature.TwoDoors, "de", "Zweitürig") .InlineEnum(CarFeature.FourDoors, "de", "Viertürig") .InlineEnum(CarFeature.FiveDoors, "de", "Fünftürige") .InlineEnum(CarFeature.Red, "de", "Rot") .InlineEnum(CarFeature.Black, "de", "Schwartz") .InlineEnum(CarFeature.White, "de", "Weiß") .Format("{0}"); ILine message = LineRoot.Global.Assembly("docs").Type("MyClass").Key("Msg") .Format("Your car has following features: {0}") .de("Ihr Auto hat folgende Eigenschaften: {0}"); CarFeature features = CarFeature.Petrol | CarFeature.Red | CarFeature.TwoDoors; // Inlined enum strings don't work as Enum (unless tool is used) Console.WriteLine(message.Value(features).Culture("de")); // But works when ILine reference is used. Console.WriteLine(message.Value(carFeature.Value(features)).Culture("de")); #endregion Snippet_7m7 } { ILine carFeature = LineRoot.Global.Assembly("docs").Type <CarFeature>().InlineEnum <CarFeature>(); CarFeature features = CarFeature.Petrol | CarFeature.FiveDoors | CarFeature.Black; Console.WriteLine(carFeature.Formulate($"{features:g}").Culture("fi")); Console.WriteLine(carFeature.Formulate($"{features:G}").Culture("fi")); Console.WriteLine(carFeature.Formulate($"{features:f}").Culture("fi")); Console.WriteLine(carFeature.Formulate($"{features:F}").Culture("fi")); Console.WriteLine(carFeature.Formulate($"{features:d}").Culture("fi")); Console.WriteLine(carFeature.Formulate($"{features:D}").Culture("fi")); Console.WriteLine(carFeature.Formulate($"{features:x}").Culture("fi")); Console.WriteLine(carFeature.Formulate($"{features:X}").Culture("fi")); } // 8. Values { #region Snippet_8a ILine line = LineRoot.Global.Key("Error").Format("ErrorCode={0}").Value(0x100); LineString result = line.ResolveString(); #endregion Snippet_8a } { #region Snippet_8b #endregion Snippet_8b } { #region Snippet_8c #endregion Snippet_8c } { #region Snippet_8d #endregion Snippet_8d } { #region Snippet_8e #endregion Snippet_8e } { #region Snippet_8f #endregion Snippet_8f } { #region Snippet_8g #endregion Snippet_8g } { #region Snippet_8h #endregion Snippet_8h } // 10. Resources { #region Snippet_10a ILine line = LineRoot.Global.Key("Error").Resource(new byte[] { 1, 2, 3 }); LineResourceBytes result = line.ResolveBytes(); #endregion Snippet_10a } { #region Snippet_10b ILine line = LineRoot.Global.Key("Error").Resource(new byte[] { 1, 2, 3 }); using (LineResourceStream result = line.ResolveStream()) { } #endregion Snippet_10b } { #region Snippet_10c #endregion Snippet_10c } { #region Snippet_10d #endregion Snippet_10d } { #region Snippet_10e #endregion Snippet_10e } { #region Snippet_10f #endregion Snippet_10f } { #region Snippet_10g #endregion Snippet_10g } { #region Snippet_10h #endregion Snippet_10h } }
/// <summary> /// Open stream /// </summary> /// <param name="key"></param> /// <returns></returns> public LineResourceStream GetResourceStream(ILine key) { Cache _cache = this.cache; // Try to read previously cached value LineResourceBytes value = default; _cache.m_lock.EnterReadLock(); try { if (_cache.data.TryGetValue(key, out value)) { if (value.Value != null) { return(new LineResourceStream(value.Line, value.Value == null ? null : new MemoryStream(value.Value), value.Exception, value.Status)); } } } finally { _cache.m_lock.ExitReadLock(); } // Open stream LineResourceStream stream = Source.GetResourceStream(key); // Store into cache? if (Options.GetCacheStreams()) { ILine cacheKey = Options.GetCloneKeys() ? key.CloneKey(LineAppender.NonResolving) : key; // Cache null value if (stream.Value == null) { _cache.m_lock.EnterWriteLock(); try { _cache.data[cacheKey] = new LineResourceBytes(value.Line, value.Exception, value.Status); return(stream); } finally { _cache.m_lock.ExitWriteLock(); } } // Read stream completely and then cache it long position = -1; int ix = 0; try { // Try to read stream length, if fails, throws an exception long len = stream.Value.Length; if (len < Options.GetMaxResourceSize()) { // Try to read position. position = stream.Value.Position; // Try to read stream completely. int len_ = (int)len; byte[] data = new byte[len]; // Read chunks while (ix < len_) { int count = stream.Value.Read(data, ix, len_ - ix); // // "returns zero (0) if the end of the stream has been reached." // if (count == 0) { break; } ix += count; } // Write data to cache if (ix == len_) { _cache.m_lock.EnterWriteLock(); try { _cache.data[cacheKey] = new LineResourceBytes(value.Line, data, value.Status); // Wrap to new stream. return(new LineResourceStream(value.Line, new MemoryStream(data), value.Status)); } finally { _cache.m_lock.ExitWriteLock(); } } else { // Reading completely failed, revert position stream.Value.Position = position; ix = 0; } } } catch (Exception) { try { // Return position. if (position > 0L) { stream.Value.Position = position; ix = 0; } } catch (Exception) { // Failed to rewind stream. } // Stream has not been rewound. Let's open it again. if (ix > 0) { stream.Value.Dispose(); return(Source.GetResourceStream(key)); } } } return(new LineResourceStream(key, (Exception)null, LineStatus.ResolveFailedNoResult)); }