public V221OutputQuotedAssetSet GetPricingStructureV221(V221Header header, V221ProviderId provider, Guid requestId, string requestParams, string structureProperties) { IModuleInfo connection = null; _connectionIndex.Locked(connections => { if (!connections.TryGetValue(header.SessionId, out connection)) { throw new ApplicationException("Ignoring request from unknown client!"); } }); //var errors = new List<V221ErrorDetail>(); string step = "GetPricingStructureV221: unknown"; try { step = "GetPricingStructureV221: calling GetPricingStructure"; // run each provider request MDSProviderId defaultProvider = V221Helpers.ToProviderId(provider); MDSResult <QuotedAssetSet> result = _providers[(int)defaultProvider].GetPricingStructure( defaultProvider, connection, requestId, true, new NamedValueSet(requestParams), new NamedValueSet(structureProperties)); step = "GetPricingStructureV221: compressing"; return(new V221OutputQuotedAssetSet( CompressionHelper.CompressToBuffer(XmlSerializerHelper.SerializeToString(result)), null)); } catch (Exception excp) { Logger.LogError("Exception: step='{0}': {1}", step, excp); return(new V221OutputQuotedAssetSet(null, new V221ErrorDetail(excp))); } }
public static void LoadProviderRules(ILogger logger, ICoreCache targetClient, string nameSpace) { logger.LogDebug("Loading market data provider rules..."); const string itemType = "MarketData.ProviderRules"; int count = 0; Assembly assembly = Assembly.GetExecutingAssembly(); const string prefix = "FpML.V5r10.ConfigData.ProviderRuleSets"; Dictionary <string, string> chosenFiles = ResourceHelper.GetResources(assembly, prefix, "xml"); if (chosenFiles.Count == 0) { throw new InvalidOperationException("Missing market data provider rules!"); } foreach (KeyValuePair <string, string> file in chosenFiles) { var ruleSet = XmlSerializerHelper.DeserializeFromString <ProviderRuleSet>(file.Value); MDSProviderId providerId = ruleSet.provider; logger.LogDebug(" Loading {0} ...", providerId); var itemProps = new NamedValueSet(); itemProps.Set(EnvironmentProp.DataGroup, "Orion.V5r10.Configuration." + itemType); itemProps.Set(EnvironmentProp.SourceSystem, "Orion"); itemProps.Set(EnvironmentProp.Function, FunctionProp.Configuration.ToString()); itemProps.Set(EnvironmentProp.Type, itemType); itemProps.Set(EnvironmentProp.Schema, "V5r10.Reporting"); itemProps.Set(EnvironmentProp.NameSpace, nameSpace); string itemName = String.Format(nameSpace + ".Configuration.{0}.{1}", itemType, providerId); targetClient.SaveObject(ruleSet, itemName, itemProps, false, TimeSpan.MaxValue); count++; } logger.LogDebug("Loaded {0} market data provider rule sets", count); }
private NamedValueSet BuildRequestParams(MDSProviderId dataProviderId) { var result = new NamedValueSet(); switch (dataProviderId) { case MDSProviderId.Bloomberg: //using (var key = new PrivateKey("MarketData", "Bloomberg", true)) //{ // result.Set(MdpConfigName.BloombergCustName, key.GetValue(MdpConfigName.BloombergCustName, null)); // result.Set(MdpConfigName.BloombergUUID, Int32.Parse(key.GetValue(MdpConfigName.BloombergUUID, null))); // result.Set(MdpConfigName.BloombergSID, Int32.Parse(key.GetValue(MdpConfigName.BloombergSID, null))); // result.Set(MdpConfigName.BloombergSidN, Int32.Parse(key.GetValue(MdpConfigName.BloombergSidN, null))); // result.Set(MdpConfigName.BloombergTsid, Int32.Parse(key.GetValue(MdpConfigName.BloombergTsid, null))); // result.Set(MdpConfigName.BloombergTSidN, Int32.Parse(key.GetValue(MdpConfigName.BloombergTSidN, null))); //} break; case MDSProviderId.ReutersIDN: case MDSProviderId.ReutersDTS: result.Set(MdpConfigName.ReutersIdleTimeoutSecs, 10); break; case MDSProviderId.GlobalIB: break; case MDSProviderId.Simulator: break; } return(result); }
private static NamedValueSet BuildRequestParamsNotUsed(MDSProviderId dataProviderId) { var result = new NamedValueSet(); switch (dataProviderId) { case MDSProviderId.Bloomberg: //using (PrivateKey key = new PrivateKey("MarketData", "Bloomberg", true)) //{ // result.Set(MdpConfigName.Bloomberg_CustName, key.GetValue(MdpConfigName.Bloomberg_CustName, "unknown")); // result.Set(MdpConfigName.Bloomberg_UUID, Int32.Parse(key.GetValue(MdpConfigName.Bloomberg_UUID, null))); // result.Set(MdpConfigName.Bloomberg_SID, Int32.Parse(key.GetValue(MdpConfigName.Bloomberg_SID, null))); // result.Set(MdpConfigName.Bloomberg_SidN, Int32.Parse(key.GetValue(MdpConfigName.Bloomberg_SidN, null))); // result.Set(MdpConfigName.Bloomberg_TSID, Int32.Parse(key.GetValue(MdpConfigName.Bloomberg_TSID, null))); // result.Set(MdpConfigName.Bloomberg_TSidN, Int32.Parse(key.GetValue(MdpConfigName.Bloomberg_TSidN, null))); //} break; //case MDSProviderId.ReutersIDN: //case MDSProviderId.ReutersDTS: // result.Set(MdpConfigName.Reuters_IdleTimeoutSecs, 10); // break; //case MDSProviderId.nabCapital: // break; //case MDSProviderId.Simulator: // break; } return(result); }
public string GetKey( MDSDictionaryType dictType, MDSRequestType requestType, MDSProviderId sourceProvider, MDSProviderId targetProvider, string sourceValue) { //return String.Format("{0};{1};{2}:{3};{4}:{5}", return ($"{dictType.ToString()};{requestType.ToString()}:{sourceProvider.ToString()};{sourceValue.ToUpper()}:{targetProvider.ToString()}"); }
public void ClearRules(MDSProviderId provider) { _rules.Locked(rules => { var newRules = rules.Where(rule => rule.SourceProvider != provider && rule.TargetProvider != provider).ToList(); rules = newRules; }); }
// base constructor public MdpBaseProvider(ILogger logger, ICoreClient client, MDSProviderId providerId, ConsumerDelegate consumer) { Logger = new FilterLogger(logger, $"{providerId}: "); Client = client; ProviderId = providerId; _marketDataMap = new MarketDataMap(logger, providerId); ConsumerCallback = consumer; SubsMapExternal = new Dictionary <Guid, RealtimeRequestMap>(); }
//private readonly ChangeCallback _Callback; public MarketDataMap(ILogger logger, MDSProviderId provider) { _logger = logger; _provider = provider; //_Callback = callback; // load static maps _forwardCache = new Dictionary <string, string>(); _reverseCache = new Dictionary <string, string>(); }
public MDSResult <QuotedAssetSet> GetPricingStructure( MDSProviderId provider, IModuleInfo clientInfo, Guid requestId, bool throwOnError, NamedValueSet requestParams, NamedValueSet structureParams) { return(_mds.GetPricingStructure( provider, clientInfo, requestId, throwOnError, requestParams, structureParams)); }
public MDSResult <QuotedAssetSet> GetMarketQuotes( MDSProviderId provider, IModuleInfo clientInfo, Guid requestId, bool throwOnError, NamedValueSet requestParams, QuotedAssetSet instruments) { // construct market data request return(_mds.GetMarketQuotes( provider, clientInfo, requestId, throwOnError, requestParams, instruments)); }
public MapRule(MDSDictionaryType dictType, MDSProviderId sourceProvider, MDSProviderId targetProvider, MDSRequestType requestType, int priority, string searchValue, string outputValue) { Disabled = false; DictType = dictType; SourceProvider = sourceProvider; TargetProvider = targetProvider; RequestType = requestType; Priority = priority; SearchValue = searchValue; OutputValue = outputValue; Regex = new Regex("^" + searchValue + "$", RegexOptions.Compiled | RegexOptions.IgnoreCase); }
public static V221ProviderId ToV221ProviderId(MDSProviderId provider) { switch (provider) { case MDSProviderId.GlobalIB: return(V221ProviderId.GlobalIB); case MDSProviderId.Bloomberg: return(V221ProviderId.Bloomberg); //case MDSProviderId.ReutersIDN: return V221ProviderId.ReutersIDN; //case MDSProviderId.ReutersDTS: return V221ProviderId.ReutersDTS; case MDSProviderId.Simulator: return(V221ProviderId.Simulator); default: throw new NotSupportedException("MDSProviderId: " + provider.ToString()); } }
public MarketDataRealtimeClient( Reference <ILogger> loggerRef, AsyncThreadQueue clientThreadQueue, ICoreClient client, MDSProviderId dataProvider) { if (dataProvider == MDSProviderId.Undefined) { throw new ArgumentNullException(nameof(dataProvider)); } ProviderId = dataProvider; _loggerRef = loggerRef?.Clone() ?? throw new ArgumentNullException(nameof(loggerRef)); ClientThreadQueue = clientThreadQueue ?? new AsyncThreadQueue(_loggerRef.Target); _mds = new MarketDataRealtimeServer(_loggerRef, clientThreadQueue, client); var serverSettings = new NamedValueSet(); serverSettings.Set(MdpConfigName.ProviderId, (int)dataProvider); _mds.ApplySettings(serverSettings); _mds.Start(); }
static void Main(string[] args) { using (Reference <ILogger> loggerRef = Reference <ILogger> .Create(new ConsoleLogger("TestMds: "))) { loggerRef.Target.LogInfo("{0} Started.", DateTime.Now); try { const MDSProviderId provider = MDSProviderId.Bloomberg; var settings = new NamedValueSet(); const int port = 9123; settings.Set(MdsPropName.Port, port); settings.Set(MdsPropName.EnabledProviders, new[] { MDSProviderId.GlobalIB.ToString(), provider.ToString() }); using (Reference <ICoreClient> clientRef = Reference <ICoreClient> .Create(new CoreClientFactory(loggerRef).SetEnv(BuildConst.BuildEnv).Create())) using (var mds = new MarketDataServer()) { mds.LoggerRef = loggerRef; mds.Client = clientRef; mds.OtherSettings = settings; mds.Start(); loggerRef.Target.LogDebug("Waiting..."); Thread.Sleep(15000); loggerRef.Target.LogDebug("Continuing..."); List <ICoreItem> marketItems; { marketItems = clientRef.Target.LoadItems <Market>(Expr.StartsWith(Expr.SysPropItemName, "Orion.V5r3.Configuration.")); } if (marketItems.Count == 0) { throw new ApplicationException("No curve definitions found!"); } using (IMarketDataClient mdc = MarketDataFactory.Create(loggerRef, null, "localhost:" + port.ToString(CultureInfo.InvariantCulture))) { foreach (ICoreItem marketItem in marketItems) { loggerRef.Target.LogDebug("Curve: {0}", marketItem.Name); var market = (Market)marketItem.Data; //PricingStructure ps = market.Items[0]; PricingStructureValuation psv = market.Items1[0]; QuotedAssetSet curveDefinition; if (psv is YieldCurveValuation valuation) { curveDefinition = valuation.inputs; } else { if (psv is FxCurveValuation curveValuation) { curveDefinition = new QuotedAssetSet { instrumentSet = curveValuation.spotRate.instrumentSet, assetQuote = curveValuation.spotRate.assetQuote } } ; else { throw new NotSupportedException("Unsupported PricingStructureValuation type: " + psv.GetType().Name); } } // call MDS MDSResult <QuotedAssetSet> mdsResponse = mdc.GetMarketQuotes( provider, null, Guid.NewGuid(), false, null, // caspar-specific parameters curveDefinition); if (mdsResponse.Error != null) { throw mdsResponse.Error; } foreach (BasicAssetValuation result in mdsResponse.Result.assetQuote) { string instrId = result.objectReference.href; foreach (BasicQuotation quote in result.quote) { string fieldId = quote.GetStandardFieldName(); loggerRef.Target.LogDebug("{0}/{1} ({2}/{3}) = [{4}]", instrId, fieldId, quote.measureType.Value, quote.quoteUnits.Value, quote.value); } } } } // using MDC mds.Stop(); }// using MDS } catch (Exception e) { loggerRef.Target.Log(e); } loggerRef.Target.LogInfo("{0} Completed.", DateTime.Now); loggerRef.Target.LogInfo("Press ENTER to exit."); Console.ReadLine(); } }
//#region IDiscoverV101 Members //public V101SessionReply DiscoverService(V101ClientInfo clientInfo) //{ // // validate new client // // - ensure configured client/server envs are the same // if (CoreHelper.ToEnvId(clientInfo.ConfigEnv) != _ServerCfg.ModuleInfo.ConfigEnv) // { // // not valid // string msg = String.Format("Client environment ({0}) <> server environment ({1})!", // clientInfo.ConfigEnv, _ServerCfg.ModuleInfo.ConfigEnv); // Logger.LogWarning(msg); // return new V101SessionReply(msg); // } // // - ensure build environment is backward compatible // if (CoreHelper.ToEnvId(clientInfo.BuildEnv) < BuildConst.BuildEnv) // { // // not valid // string msg = String.Format("Client build environment ({0}) < server build environment ({1})!", // clientInfo.BuildEnv, BuildConst.BuildEnv); // Logger.LogWarning(msg); // return new V101SessionReply(msg); // } // // - ensure STG/PRD envs servers only accessed by valid clients // if ((_ServerCfg.ModuleInfo.ConfigEnv >= EnvId.STG_StagingLive) && (clientInfo.CompPTok != _ServerCfg.ModuleInfo.CompPTok)) // { // Logger.LogDebug("Client signature ({0}) <> server signature ({1})!", // clientInfo.CompPTok, _ServerCfg.ModuleInfo.CompPTok); // } // // grant access // Guid token = Guid.NewGuid(); // _GrantedSessions.Locked((tokens) => tokens.Add(new GrantedSession(token, clientInfo))); // return new V101SessionReply(token, null); //} //#endregion private MDSProviderId ChooseProvider(IEnumerable <InformationSource> sources, MDSProviderId[] activeProviders, MDSProviderId defaultProvider) { if (sources != null) { foreach (InformationSource source in sources) { if (source.rateSource?.Value != null) { if (EnumHelper.TryParse(source.rateSource.Value, true, out MDSProviderId result)) { // check preferred provider is active if (activeProviders.Any(enabledProvider => result == enabledProvider)) { return(result); } } else { // log warning Logger.LogWarning("ChooseProvider: Unknown MDSProviderId: '{0}'", source.rateSource.Value); } } } // log warning Logger.LogWarning("ChooseProvider: Using default MDSProviderId: '{0}'", defaultProvider); } return(defaultProvider); }
static void Main(string[] args) { Reference <ILogger> loggerRef = Reference <ILogger> .Create(new ConsoleLogger("TestWebMdc: ")); loggerRef.Target.LogInfo("Running..."); try { // get some market quotes from for a Highlander FX curve // and get a Highlander volatility matrix const string curveName = "Orion.V5r3.Configuration.PricingStructures.QR_LIVE.FxCurve.AUD-USD"; QuotedAssetSet quotedAssetSet; using (ICoreClient client = new CoreClientFactory(loggerRef).SetEnv(BuildConst.BuildEnv).Create()) { ICoreItem marketItem = client.LoadItem <Market>(curveName); if (marketItem == null) { throw new ApplicationException("Market '" + curveName + "' not found!"); } var market = (Market)marketItem.Data; //PricingStructure ps = market.Items[0]; PricingStructureValuation psv = market.Items1[0]; var valuation = psv as YieldCurveValuation; if (valuation != null) { quotedAssetSet = valuation.inputs; } else { var curveValuation = psv as FxCurveValuation; if (curveValuation != null) { quotedAssetSet = new QuotedAssetSet { instrumentSet = curveValuation.spotRate.instrumentSet, assetQuote = curveValuation.spotRate.assetQuote } } ; else { throw new NotSupportedException("Unsupported PricingStructureValuation type: " + psv.GetType().Name); } } } //Copied from the working version const int port = 9123; // create MDS client using (IMarketDataClient mdc = MarketDataFactory.Create(loggerRef, null, "localhost:" + port.ToString(CultureInfo.InvariantCulture)))//This was null in the 3rd parameter. { { const MDSProviderId providerId = MDSProviderId.Bloomberg; loggerRef.Target.LogInfo("----- {0} Market Quotes -----", providerId); QuotedAssetSet quotes = mdc.GetMarketQuotes( providerId, null, Guid.NewGuid(), true, null, quotedAssetSet).Result; LogResults(loggerRef.Target, quotes); } { const MDSProviderId providerId = MDSProviderId.GlobalIB; loggerRef.Target.LogInfo("----- {0} Volatility Matrix -----", providerId); var matrixProps = new NamedValueSet(); matrixProps.Set("Function", "MarketData"); matrixProps.Set("Market", "EOD"); matrixProps.Set("CurveName", "AUD-Swap"); matrixProps.Set("PricingStructureType", "RateATMVolatilityMatrix"); QuotedAssetSet matrix = mdc.GetPricingStructure( providerId, null, Guid.NewGuid(), true, null, matrixProps).Result; LogResults(loggerRef.Target, matrix); } } } catch (Exception e) { loggerRef.Target.Log(e); } loggerRef.Target.LogInfo("Completed."); loggerRef.Target.LogInfo("Press ENTER to exit."); Console.ReadLine(); }
/// <summary> /// /// </summary> /// <param name="header"></param> /// <param name="v221Provider"></param> /// <param name="requestId"></param> /// <param name="requestParams"></param> /// <param name="zsQuotedAssetSet"></param> /// <returns></returns> public V221OutputQuotedAssetSet GetMarketQuotesV221(V221Header header, V221ProviderId v221Provider, Guid requestId, string requestParams, byte[] zsQuotedAssetSet) { IModuleInfo connection = null; _connectionIndex.Locked(connections => { if (!connections.TryGetValue(header.SessionId, out connection)) { throw new ApplicationException("Ignoring request from unknown client!"); } }); //var errors = new List<V221ErrorDetail>(); var result = new QuotedAssetSet(); string step = "GetMarketQuotesV221: unknown"; try { step = "GetMarketQuotesV221: decompressing"; // deserialise inputs var receivedRequest = XmlSerializerHelper.DeserializeFromString <QuotedAssetSet>(CompressionHelper.DecompressToString(zsQuotedAssetSet)); //debug dump request //this.Logger.LogDebug("Received: {0}", XmlSerializerHelper.SerializeToString<QuotedAssetSet>(receivedRequest)); // end debug step = "GetMarketQuotesV221: splitting"; // split request into provider-specific requests // build unique instrumentSet var instrumentMap = new Dictionary <string, Asset>(); foreach (Asset asset in receivedRequest.instrumentSet.Items) { string assetId = asset.id; instrumentMap[assetId.ToLower()] = asset; } // now split quotes based on provider preferences MDSProviderId defaultProvider = V221Helpers.ToProviderId(v221Provider); int providerCount = Enum.GetValues(typeof(MDSProviderId)).Length; var providerRequests = new RequestContainer[providerCount]; for (int i = 0; i < providerRequests.Length; i++) { providerRequests[i] = new RequestContainer(); } int requestedQuoteCount = 0; foreach (BasicAssetValuation valuation in receivedRequest.assetQuote) { string assetId = valuation.objectReference.href; if (!instrumentMap.TryGetValue(assetId.ToLower(), out var asset)) { throw new ApplicationException($"Cannot find asset '{assetId}' in instrument set"); } foreach (BasicQuotation quote in valuation.quote) { if (!quote.valueSpecified) { requestedQuoteCount++; MDSProviderId quoteProvider = ChooseProvider(quote.informationSource, _activeProviders, defaultProvider); RequestContainer requestContainer = providerRequests[(int)quoteProvider]; requestContainer.InstrumentMap[assetId.ToLower()] = asset; // merge the quotes if (!requestContainer.ValuationMap.TryGetValue(assetId.ToLower(), out var bav)) { // missing - create bav = new BasicAssetValuation { objectReference = new AnyAssetReference { href = assetId } }; requestContainer.ValuationMap[assetId.ToLower()] = bav; } // append the asset quotes var quotes = new List <BasicQuotation>(); if (bav.quote != null) { quotes.AddRange(bav.quote); } quotes.Add(quote); bav.quote = quotes.ToArray(); } } } if (requestedQuoteCount == 0) { throw new ApplicationException("No quotes requested!"); } step = "GetMarketQuotesV221: calling providers"; // run each provider request foreach (MDSProviderId activeProvider in _activeProviders) { RequestContainer requestContainer = providerRequests[(int)activeProvider]; if (requestContainer.InstrumentMap.Count > 0) { // request is not empty - call the MDS provider var types = new List <ItemsChoiceType19>(); foreach (var asset in requestContainer.InstrumentMap.Values) { var assetTypeFpML = AssetTypeConvertor.ParseEnumStringToFpML(asset.id);//TODO The id must contain the asset descriptor. types.Add(assetTypeFpML); } var instrumentSet = new InstrumentSet { Items = requestContainer.InstrumentMap.Values.ToArray(), ItemsElementName = types.ToArray() }; var providerRequest = new QuotedAssetSet { instrumentSet = instrumentSet, assetQuote = requestContainer.ValuationMap.Values.ToArray() }; step = "GetMarketQuotesV221: calling " + activeProvider.ToString(); QuotedAssetSet providerResult = _providers[(int)activeProvider].GetMarketQuotes( activeProvider, connection, requestId, true, new NamedValueSet(requestParams), providerRequest).Result; // combine provider-specific results result = result.Merge(providerResult, false, true, true); } } step = "GetMarketQuotesV221: compressing"; return(new V221OutputQuotedAssetSet( CompressionHelper.CompressToBuffer(XmlSerializerHelper.SerializeToString(result)), null)); } catch (Exception excp) { Logger.LogError("Exception: step='{0}': {1}", step, excp); return(new V221OutputQuotedAssetSet(null, new V221ErrorDetail(excp))); } }
public string Convert( MDSDictionaryType dictType, MDSRequestType requestType, MDSProviderId sourceProvider, MDSProviderId targetProvider, string sourceValue, ConvertFailMode failMode) { // method: // 1. check for cached result // 2. find relevant maps (by dicttype, reqtype, assettype, source, target) // 3. process maps in priority order until hit, fail if no hit // 4. save outbound and inbound results in cache if (dictType == MDSDictionaryType.Undefined) { throw new ArgumentNullException(nameof(dictType)); } if (requestType == MDSRequestType.Undefined) { throw new ArgumentNullException(nameof(requestType)); } //if (assetType == MDSAssetType.Undefined) // throw new ArgumentNullException("assetType"); if (sourceProvider == MDSProviderId.Undefined) { throw new ArgumentNullException(nameof(sourceProvider)); } if (targetProvider == MDSProviderId.Undefined) { throw new ArgumentNullException(nameof(targetProvider)); } if (sourceValue == null) { throw new ArgumentNullException(nameof(sourceValue)); } sourceValue = sourceValue.Trim().ToUpper(); if (sourceValue == "") { throw new ArgumentNullException(nameof(sourceValue)); } const string cUnknownValue = "[unknown]"; // check for cached result string forwardKey = GetKey(dictType, requestType, //assetType, sourceProvider, targetProvider, sourceValue); lock (_forwardCache) { if (_forwardCache.TryGetValue(forwardKey, out var cachedResult)) { //Logger.LogDebug("Converted {0} {1} '{2}' to {3} '{4}' (via forward cache)", // sourceProvider.ToString(), dictType.ToString(), sourceValue, targetProvider.ToString(), cachedResult); return(cachedResult); } } // find relevant maps (by dicttype, reqtype, assettype, source, target) var maps = new List <MapRule>(); _rules.Locked((rules) => { foreach (var rule in rules) { if ((!rule.Disabled) && (rule.DictType == MDSDictionaryType.Undefined || (rule.DictType == dictType)) && (rule.SourceProvider == MDSProviderId.Undefined || (rule.SourceProvider == sourceProvider)) && (rule.TargetProvider == MDSProviderId.Undefined || (rule.TargetProvider == targetProvider)) //&& (rule.AssetIdType == MDSAssetType.Undefined || (rule.AssetIdType == assetType)) && (rule.RequestType == MDSRequestType.Undefined || (rule.RequestType == requestType))) { maps.Add(rule); } } }); // process maps in priority order until hit, fail if no hit string result = sourceValue; bool replaced = false; foreach (var map in maps) { Match match = map.Regex.Match(sourceValue); if (match.Success) { result = map.Regex.Replace(sourceValue, map.OutputValue); replaced = true; break; } } if (replaced) { result = result.Trim().ToUpper(); //_Logger.LogDebug("Converted {0} {1} '{2}' to {3} '{4}' (via mapping rules)", // sourceProvider.ToString(), dictType.ToString(), sourceValue, targetProvider.ToString(), result); // update forward and reverse caches UpdateForwardCache(forwardKey, result); string reverseKey = GetKey(dictType, requestType, //assetType, targetProvider, sourceProvider, result); UpdateReverseCache(reverseKey, sourceValue); } else { // no replacement rules - try the reverse cache string cachedResult; bool foundInReverseCache; lock (_reverseCache) { foundInReverseCache = _reverseCache.TryGetValue(forwardKey, out cachedResult); } if (foundInReverseCache) { _logger.LogDebug("Converted {0} {1} '{2}' to {3} '{4}' (via reverse cache)", sourceProvider.ToString(), dictType.ToString(), sourceValue, targetProvider.ToString(), cachedResult); // update forward cache UpdateForwardCache(forwardKey, cachedResult); return(cachedResult); } // exhausted all conversion options _logger.LogWarning("Cannot convert {0} {1} '{2}' to {3} (no matching map found)", sourceProvider.ToString(), dictType.ToString(), sourceValue, targetProvider.ToString()); switch (failMode) { case ConvertFailMode.PassThrough: result = sourceValue; break; case ConvertFailMode.ReturnNull: result = null; break; case ConvertFailMode.ReturnUnknown: result = cUnknownValue; break; default: throw new ApplicationException( String.Format("Cannot convert {0} {1} '{2}' to {3} ", sourceProvider.ToString(), dictType.ToString(), sourceValue, targetProvider.ToString())); } } return(result); }