Пример #1
0
        public async Task <string> LoginAsync(string userName, string password, AccountIdApi account, string url, List <KeyValuePair <string, string> > KeyValues)
        {
            try
            {
                await PreAPICall();

                var request = new HttpRequestMessage(HttpMethod.Post, $"{constants.serverUrl}/{url}");

                request.Content = new FormUrlEncodedContent(KeyValues);
                var respons = await httpClient.SendAsync(request);

                var jwt = await respons.Content.ReadAsStringAsync();

                JObject jwtDynamic  = JsonConvert.DeserializeObject <dynamic>(jwt);
                var     accessToken = jwtDynamic.Value <string>("access_token");
                Debug.WriteLine(jwt);
                AfterAPICall();
                return(accessToken);
            }
            catch (Exception ex)
            {
                var logged = new LoggedException($"Error while trying to call login api {url}", ex);
                await logged.LoggAPI();
            }
            return(null);
        }
Пример #2
0
        public override int WriteException(LoggedException e)
        {
            XmlDocument doc        = new XmlDocument();
            XmlNode     xException = doc.AppendChild(doc.CreateElement("event"));

            xException.AppendChild(doc.CreateElement("group")).InnerText      = e.Group;
            xException.AppendChild(doc.CreateElement("type")).InnerText       = e.Type;
            xException.AppendChild(doc.CreateElement("details")).InnerText    = e.Details;
            xException.AppendChild(doc.CreateElement("message")).InnerText    = e.Message;
            xException.AppendChild(doc.CreateElement("stacktrace")).InnerText = e.StackTrace;
            xException.AppendChild(doc.CreateElement("clientip")).InnerText   = e.ClientIp;
            xException.AppendChild(doc.CreateElement("hostip")).InnerText     = e.HostIp;

            XmlNode xApplication = xException.AppendChild(doc.CreateElement("application"));

            xApplication.AppendChild(doc.CreateElement("id")).InnerText   = e.ApplicationId.ToString();
            xApplication.AppendChild(doc.CreateElement("name")).InnerText = e.ApplicationName;
            xApplication.AppendChild(doc.CreateElement("type")).InnerText = e.ApplicationType.ToString();

            EventLog.WriteEntry(xException.OuterXml, EventLogEntryType.Error);

            //EventLog does not synchronously return IDs for new events, so return 1
            //This module is intended to log to a centralized logging source, not the local event log
            //This module is provided for exabple purposes only
            return(1);
        }
Пример #3
0
        public async Task <bool> DeleteAsync(string id, string url)
        {
            try
            {
                await PreAPICall();

                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Pt_Hippo_Mobile.Helpers.Settings.AccessToken);
                var response = await httpClient.DeleteAsync($"{constants.serverUrl}/{url}/{id}");

                AfterAPICall();
                if (response.IsSuccessStatusCode == false)
                {
                    await ValidateErrors(response);

                    return(false);
                }
                return(response.IsSuccessStatusCode);
            }
            catch (Exception ex)
            {
                var logged = new LoggedException($"Error while trying to call deleteasync api {url}", ex);
                await logged.LoggAPI();
            }
            return(false);
        }
Пример #4
0
        public async Task <T> GetClientId(string url)
        {
            try
            {
                await PreAPICall();

                HttpResponseMessage response = await httpClient.GetAsync($"{constants.serverUrl}/{url}");

                var stream = await response.Content.ReadAsStreamAsync();

                StreamReader readStream = new StreamReader(stream, Encoding.UTF8);
                var          json       = readStream.ReadToEnd();
                var          account    = JsonConvert.DeserializeObject <T>(json);
                AfterAPICall();
                if (response.IsSuccessStatusCode == false)
                {
                    await ValidateErrors(response);

                    return(default(T));
                }
                return(account);
            }
            catch (Exception ex)
            {
                var logged = new LoggedException($"Error while trying to call getclientid api {url}", ex);
                await logged.LoggAPI();
            }
            return(default(T));
        }
Пример #5
0
        public async Task <T> GetAsync(string api, string id)
        {
            try
            {
                await PreAPICall();

                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Pt_Hippo_Mobile.Helpers.Settings.AccessToken);

                string url = id == null ? $"{constants.serverUrl}/{api}" : $"{constants.serverUrl}/{api}/" + id;

                var result = await httpClient.GetAsync(url);

                if (result.IsSuccessStatusCode == false)
                {
                    AfterAPICall();
                    await ValidateErrors(result);

                    return(default(T));
                }

                var json = await result.Content.ReadAsStringAsync();

                var taskModels = JsonConvert.DeserializeObject <T>(json);

                AfterAPICall();
                return(taskModels);
            }
            catch (Exception ex)
            {
                var logged = new LoggedException($"Error while trying to call getasync api {api}", ex);
                await logged.LoggAPI();
            }
            return(default(T));
        }
Пример #6
0
        //update List Async
        public async Task <bool> PutListAsync(List <T> data, string api)
        {
            try
            {
                await PreAPICall();

                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Pt_Hippo_Mobile.Helpers.Settings.AccessToken);
                var         json        = JsonConvert.SerializeObject(data);
                HttpContent httpContent = new StringContent(json);
                httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var result = await httpClient.PutAsync($"{constants.serverUrl}/{api}", httpContent);

                AfterAPICall();
                if (result.IsSuccessStatusCode == false)
                {
                    await ValidateErrors(result);

                    return(false);
                }
                return(result.IsSuccessStatusCode);
            }
            catch (Exception ex)
            {
                var logged = new LoggedException($"Error while trying to call putlist api {api}", ex);
                await logged.LoggAPI();
            }
            return(false);
        }
Пример #7
0
        public async Task <List <T> > GetListOptionalId(string api, string id, bool authorize = true)
        {
            try
            {
                await PreAPICall();

                if (authorize)
                {
                    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Pt_Hippo_Mobile.Helpers.Settings.AccessToken);
                }
                string url = id == null ? $"{constants.serverUrl}/{api}" : $"{constants.serverUrl}/{api}/" + id;

                var json = await httpClient.GetStringAsync(url);

                var taskModels = JsonConvert.DeserializeObject <List <T> >(json);
                AfterAPICall();
                return(taskModels);
            }
            catch (Exception ex)
            {
                var logged = new LoggedException($"Error while trying to call  api {api}", ex);
                await logged.LoggAPI();
            }
            return(null);
        }
Пример #8
0
        private static int ReadDayCodeLine(string line)
        {
            CheckNullLine(line, "day code");
            LoggedException.RaiseIf(line[0] != '-' || line.Length != 6, nameof(PASReader), "Invalid day code format");

            return(int.Parse(line.Substring(1, 5)));
        }
Пример #9
0
        private ConstructorInfo AddCtor(Type t)
        {
            Log.Verbose(nameof(ReflectionCache), $"Adding constructor for type '{t.Name}' to cache");
            ConstructorInfo result = t.GetConstructor(ctorTypes);

            LoggedException.RaiseIf(result == null, $"Cannot find serializable constructor for type: '{t.Name}'");
            ctors = ctors.Concat(result);
            return(result);
        }
Пример #10
0
 // avoid the exception handling middleware which would log the exception again
 public virtual IActionResult HandleError(string message, LoggedException ex)
 {
     return(View(nameof(HomeController.Error)
                 , new ErrorViewModel {
         RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier
     }));
     // a bit of cargo-culting here - Activity is some sort of diagnostic thing
     // as presumably is TraceIdentifier
 }
Пример #11
0
        private EntrySaveState InternalSaveEntry(Entry entry, TrackbackInfoCollection trackbackList, CrosspostInfoCollection crosspostList)
        {
            EntrySaveState rtn = EntrySaveState.Failed;

            // we want to prepopulate the cross post collection with the crosspost footer
            if (dasBlogSettings.SiteConfiguration.EnableCrossPostFooter && dasBlogSettings.SiteConfiguration.CrossPostFooter != null &&
                dasBlogSettings.SiteConfiguration.CrossPostFooter.Length > 0)
            {
                foreach (CrosspostInfo info in crosspostList)
                {
                    info.CrossPostFooter = dasBlogSettings.SiteConfiguration.CrossPostFooter;
                }
            }

            // now save the entry, passign in all the necessary Trackback and Pingback info.
            try
            {
                // if the post is missing a title don't publish it
                if (entry.Title == null || entry.Title.Length == 0)
                {
                    entry.IsPublic = false;
                }

                // if the post is missing categories, then set the categories to empty string.
                if (entry.Categories == null)
                {
                    entry.Categories = "";
                }

                rtn = dataService.SaveEntry(
                    entry,
                    MaybeBuildWeblogPingInfo(),
                    entry.IsPublic
                                                ? trackbackList
                                                : null,
                    MaybeBuildPingbackInfo(entry),
                    crosspostList);

                //TODO: SendEmail(entry, siteConfig, logService);
            }
            catch (Exception ex)
            {
                //TODO: Do something with this????
                // StackTrace st = new StackTrace();
                // logService.AddEvent(new EventDataItem(EventCodes.Error, ex.ToString() + Environment.NewLine + st.ToString(), ""));

                LoggedException le  = new LoggedException("file failure", ex);
                var             edi = new EventDataItem(EventCodes.Error, null
                                                        , "Failed to Save a Post on {date}", System.DateTime.Now.ToShortDateString());
                logger.LogError(edi, le);
            }

            // we want to invalidate all the caches so users get the new post
            // BreakCache(entry.GetSplitCategories());

            return(rtn);
        }
Пример #12
0
        public void CanCreateLoggedException()
        {
            const string msg1 = "Message 1";
            const string msg2 = "Message 2";
            var          ex   = new LoggedException(msg1, new Exception(msg2));

            Assert.AreEqual(ex.Message, msg1);
            Assert.AreEqual(ex.InnerException.Message, msg2);
        }
Пример #13
0
        /// <summary>
        /// Removes an item at the specified index.
        /// </summary>
        /// <param name="index"> The specified index. </param>
        /// <exception cref="LoggedException"> The index was out of range. </exception>
        public void RemoveAt(int index)
        {
            LoggedException.RaiseIf(index >= Count, nameof(ThreadSafeList <T>), "index out of range");
            EnterWriteLock();

            ShiftLeft(index);
            --size;

            ExitWriteLock();
        }
Пример #14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="StopableThread"/> class.
 /// </summary>
 /// <param name="init"> The function to call when initialzing the run loop (can be <see langword="null"/>). </param>
 /// <param name="term"> The function to call when terminating the run loop (can be <see langword="null"/>). </param>
 /// <param name="tick"> The function that handles the thread tick, cannot be <see langword="null"/>. </param>
 /// <param name="name"> The name of the thread. </param>
 public StopableThread(ThreadStart init, ThreadStart term, ThreadStart tick, string name = null)
 {
     LoggedException.RaiseIf(tick == null, nameof(StopableThread), "Unable to create thread!", new ArgumentNullException("tick", "tick cannot be null!"));
     TickCooldown = 10;
     this.init    = init;
     this.term    = term;
     this.tick    = tick;
     Name         = name;
     nameSet      = !string.IsNullOrEmpty(name);
     thread       = ThreadBuilder.CreateSTA(Run, name);
 }
Пример #15
0
 public static void LogTrace(this ILogger logger, EventDataItem edi, LoggedException ex = null)
 {
     if (ex != null)
     {
         logger.LogTrace(100, ex, edi.UserMessage, edi.Params);
     }
     else
     {
         logger.LogTrace(100, edi.UserMessage, edi.Params);
     }
 }
Пример #16
0
        /// <summary>
        /// Inserts an item at the specified index.
        /// </summary>
        /// <param name="index"> The position of the new item. </param>
        /// <param name="item"> The item to be added. </param>
        /// <exception cref="LoggedException"> The index was out of range. </exception>
        public void Insert(int index, T item)
        {
            LoggedException.RaiseIf(index >= Count, nameof(ThreadSafeList <T>), "index out of range");
            EnterWriteLock();

            ShiftRight(index);
            data[index] = item;
            ++size;

            ExitWriteLock();
        }
Пример #17
0
        private static RouteStop ReadStopStartLine(string line)
        {
            CheckNullLine(line, "route start line");
            LoggedException.RaiseIf(line[0] != '>' || line[8] != ',' || line.Length != 13, nameof(PASReader), "Invalid route start format");

            RouteStop result = new RouteStop {
                Id = line.Substring(1, 6)
            };

            result.SetLeaveFromString(line.Substring(9, 4));
            return(result);
        }
Пример #18
0
        private static BigRouteStop ReadBigStopLine(string line)
        {
            CheckNullLine(line, "big route line");
            LoggedException.RaiseIf(line[0] != '+' || line[8] != ',' || line.Length != 18, nameof(PASReader), "Invalid big route format");

            BigRouteStop result = new BigRouteStop {
                Id = line.Substring(1, 6)
            };

            result.SetLeaveFromString(line.Substring(9, 4));
            result.SetArriveFromString(line.Substring(14, 4));
            return(result);
        }
Пример #19
0
        private static void CheckValidity(string line)
        {
            CheckNullLine(line, "validity");
            LoggedException.RaiseIf(line[0] != '&' || line[9] != '-' || line.Length != 18, nameof(PASReader), "Invalid validity format");

            DateTime start = DateTime.ParseExact(line.Substring(1, 8), "ddMMyyyy", CultureInfo.InvariantCulture);
            DateTime end   = DateTime.ParseExact(line.Substring(10, 8), "ddMMyyyy", CultureInfo.InvariantCulture);

            if (start > DateTime.Now)
            {
                Log.Warning(nameof(PASReader), $"Validty is not yet active ({start})");
            }
            if (end < DateTime.Now)
            {
                Log.Warning(nameof(PASReader), $"Validity is no longer active ({end})");
            }
        }
Пример #20
0
        private static RETRoute ReadRouteLine(string line)
        {
            CheckNullLine(line, "route");
            LoggedException.RaiseIf(line[0] != '#' || line[2] != ',' || line[9] != ',' ||
                                    line[13] != ',' || line[15] != ',' || line.Length != 21, nameof(PASReader), "Invalid route line format");

            RETRoute result = new RETRoute
            {
                CompanyId = int.Parse(line.Substring(3, 5)),
                LineNum   = int.Parse(line.Substring(10, 2)),
                Direction = (Direction)Convert.ToInt32(line[14]),
                RouteNum  = int.Parse(line.Substring(16, 4))
            };

            result.SetTypeFromChar(line[1]);

            return(result);
        }
Пример #21
0
        /// <summary>
        /// Gets the specified element without removing it.
        /// </summary>
        /// <param name="index"> The index of the specific element to peek. </param>
        /// <returns> The element at the specified position or default(T) when the queue was empty. </returns>
        /// <exception cref="LoggedException"> The index was out of bounds. </exception>
        /// <exception cref="LoggedException"> An unhandled exception occured whilst excecuting the method. </exception>
        public T Peek(int index)
        {
            EnterWriteLock();

            if (size == 0)
            {
                ExitWriteLock();
                return(default(T));
            }
            if (index >= size)
            {
                ExitWriteLock();
                LoggedException.Raise(nameof(ThreadSafeQueue <T>), "index must be smaller than the size of the queue", new IndexOutOfRangeException());
            }

            T result = data[(head + index) % data.Length];

            ExitWriteLock();
            return(result);
        }
Пример #22
0
        public async Task <T> Post(string api, object data)
        {
            try
            {
                await PreAPICall();

                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Pt_Hippo_Mobile.Helpers.Settings.AccessToken);

                var         json        = JsonConvert.SerializeObject(data);
                HttpContent httpContent = new StringContent(json);
                httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                string url    = $"{constants.serverUrl}/{api}";
                var    result = await httpClient.PostAsync(url, httpContent);

                var Data = await result.Content.ReadAsStringAsync();

                if (api == URLConfig.MobileLogging)
                {
                    AfterAPICall();
                    return(default(T));
                }

                if (result.IsSuccessStatusCode == false)
                {
                    AfterAPICall();
                    await ValidateErrors(result);

                    return(default(T));
                }

                var taskModels = JsonConvert.DeserializeObject <T>(Data);
                AfterAPICall();
                return(taskModels);
            }
            catch (Exception ex)
            {
                var logged = new LoggedException($"Error while trying to call postdata api {api}", ex);
                await logged.LoggAPI();
            }
            return(default(T));
        }
Пример #23
0
        public async Task <T> GetSearch(string api, string searchtext, int pagesize, int pagenumber, string zipcode, DateTime startdate, DateTime enddate, double minhourrate, double maxhourate)
        {
            try
            {
                await PreAPICall();

                httpClient.DefaultRequestHeaders.Authorization =
                    new AuthenticationHeaderValue("Bearer", Pt_Hippo_Mobile.Helpers.Settings.AccessToken);
                //string json = "";
                httpClient.DefaultRequestHeaders.Authorization =
                    new AuthenticationHeaderValue("Bearer", Pt_Hippo_Mobile.Helpers.Settings.AccessToken);
                //string json = "";
                //GET /api/job/getBasicSearchForJobs/{pageSize}/{pageNumber}/{zipCode}/{startDate}/{endDate}/{minHourRate}/{maxHourRate}
                string startDateText = "null";
                string endDateText   = "null";
                if (startdate != DateTime.MinValue)
                {
                    startDateText = startdate.Date.ToString("MM-dd-yyyy");
                }

                if (enddate != DateTime.MinValue)
                {
                    endDateText = enddate.Date.ToString("MM-dd-yyyy");
                }

                string url =
                    $"{constants.serverUrl}/{api}/{pagesize}/{pagenumber}/{zipcode}/{startDateText}/{endDateText}/{minhourrate}/{maxhourate}";
                var json = await httpClient.GetStringAsync(url);

                var taskModels = JsonConvert.DeserializeObject <T>(json);
                AfterAPICall();
                return(taskModels);
            }
            catch (Exception ex)
            {
                var logged = new LoggedException($"Error while trying to call getsearchapi api {api}", ex);
                await logged.LoggAPI();
            }

            return(default(T));
        }
Пример #24
0
        /// <summary>
        /// Reads specified types from a specified file.
        /// </summary>
        /// <typeparam name="T"> The type attempt to serialize to. </typeparam>
        /// <param name="fileName"> A absolute or relative path to the file. </param>
        /// <param name="ctor"> A function to user as the types constructor. </param>
        /// <returns> A list of serialized objects. </returns>
        private static List <T> ReadTypeFromFile <T>(string fileName)
            where T : ISerializable, new()
        {
            fileName = $"{Settings.Default.DataDirectory}{fileName}";                   // Get the full path to the file.
            List <T> result = new List <T>();

            curLine = 0;

            LoggedException.RaiseIf(!(fileName.EndsWith(".csv") || fileName.EndsWith(".HLT")), nameof(CSVReader),      // Raise an exception if the files isn't a .csv file.
                                    $"Cannot open file with extension {Path.GetExtension(fileName)}, supply .csv file");

            try
            {
                using (StreamReader sr = new StreamReader(fileName))                    // Open a read stream to the file.
                {
                    Log.Verbose(nameof(CSVReader), $"Started parsing file: '{Path.GetFileName(fileName)}'");
                    char[] splitChars = fileName.EndsWith(".csv") ? new char[] { ';' } : new char[] { ',' };

                    string line;
                    while ((line = sr.ReadLine()) != null)                              // Read all lines.
                    {
                        ++curLine;                                                      // Increment the current line.

                        T cur;
                        if (DeserializeType(line, splitChars, out cur))
                        {
                            result.Add(cur);                                                        // Deserialzie a type from the current line.
                        }
                    }

                    Log.Info(nameof(CSVReader), $"File contains {result.Count} readable entries");
                }
            }
            catch (Exception e)
            {
                Log.Fatal(nameof(CSVReader), new FileLoadException($"An unhandled exception was raised during the processing of file: '{Path.GetFullPath(fileName)}'", e));
            }

            Log.Verbose(nameof(CSVReader), $"Finished parsing file: '{Path.GetFileName(fileName)}'");
            return(result);
        }
Пример #25
0
        /// <summary>
        /// Gets or sets a value at the specified index.
        /// </summary>
        /// <param name="index"> The secified index. </param>
        /// <returns> The value at the specified index. </returns>
        /// <exception cref="LoggedException"> The index was out of range. </exception>
        public T this[int index]
        {
            get
            {
                LoggedException.RaiseIf(index >= Count, nameof(ThreadSafeList <T>), "index out of range");

                EnterReadLock();
                T result = data[index];
                ExitReadLock();

                return(result);
            }
            set
            {
                LoggedException.RaiseIf(index >= Count, nameof(ThreadSafeList <T>), "index out of range");

                EnterWriteLock();
                data[index] = value;
                ExitWriteLock();
            }
        }
Пример #26
0
 private void LoggedExceptionHandler(object sender, EventArgs <Exception> e)
 {
     LoggedException?.Invoke(sender, new EventArgs <Exception>(e.Argument));
 }
 /// <summary>
 /// Adds the specified logged exception.
 /// </summary>
 /// <param name="loggedException">The logged exception.</param>
 public void Add(LoggedException loggedException)
 {
     if (loggedException == null)
     {
         throw new ArgumentNullException("loggedException");
     }
     this.loggedExceptions.Add(loggedException);
 }
        public List <EventDataDisplayItem> GetEventsForDay(DateTime date)
        {
            List <EventDataDisplayItem> events = new List <EventDataDisplayItem>();
            bool          isPreviousEvent      = false;
            StringBuilder stackTrace           = new StringBuilder();

            // add in the stacktrace to the last event
            void UpdatePreviousEvent()
            {
                EventDataDisplayItem existingEddi = events[events.Count - 1];

                var completeEddi = new EventDataDisplayItem(
                    existingEddi.EventCode
                    , existingEddi.HtmlMessage + stackTrace
                    , existingEddi.Date);

                events[events.Count - 1] = completeEddi;
                stackTrace.Clear();
            }

            try
            {
                // process all the lines in the log for the given date
                // ignore info not related to DasBlog events i.e. Microsoft logging
                // and aggregate stack traces for dasBlog events with the event line
                using (var repo = repoFactory.GetRepo())
                {
                    foreach (var line in repo.GetEventLines(date))
                    {
                        char[] chars = line.ToCharArray();
                        if (chars.Length > 0 && !Char.IsDigit(chars[0]))
                        {
                            goto stack_trace;
                        }
                        // any line not starting with a date is treated as a stack trace frome
                        (bool success, EventDataDisplayItem eddi) = parser.Parse(line);
                        if (success)
                        {
                            goto event_line;
                        }
                        goto non_event_line;
                        // any line that could not be parsed is assumed not to be a dasblog event
                        // and is ignored
event_line:
                        if (isPreviousEvent)                                    // previous event still in progress
                        {
                            UpdatePreviousEvent();
                        }
                        events.Add(eddi);
                        isPreviousEvent = true;
                        continue;
non_event_line:
                        if (isPreviousEvent)                                    // previous event still in progress
                        {
                            UpdatePreviousEvent();
                        }
                        isPreviousEvent = false;
                        continue;
stack_trace:
                        if (isPreviousEvent)
                        {
                            stackTrace.Append("<br>");
                            stackTrace.Append(line);
                        }
                        continue;
                    }
                }

                if (isPreviousEvent)
                {
                    UpdatePreviousEvent();
                }
            }
            catch (Exception e)
            {
                LoggedException le = new LoggedException("file failure", e);
                logger.LogError(new EventDataItem(EventCodes.Error, null
                                                  , "Failed to process the log file for {date}", date.ToShortDateString())
                                , le);
                throw le;
            }
            return(events);
        }
Пример #29
0
 private static void RaiseLinqException(string method, Exception inner)
 {
     LoggedException.Raise(nameof(ArrayExtensions), $"{method} has encountered an unhandled exception", inner);
 }
Пример #30
0
 internal static void AddLogger(IDisposable sender)
 {
     LoggedException.RaiseIf(loggerActive, nameof(ConsoleLogger), "A logger is already active!");
     loggerActive   = true;
     loggerDispose += sender.Dispose;
 }
Пример #31
0
 /// <summary>
 /// Attemps to enter a write lock.
 /// </summary>
 /// <exception cref="LoggedException"> Method timed out. </exception>
 protected void EnterWriteLock()
 {
     LoggedException.RaiseIf(!locker.TryEnterWriteLock(LockTimeout), nameof(LockableObject), "Unable to enter write lock");
     writeActive = true;
 }