private void AddCacheKey(IInvocation invocation, IRedisCacheService redisCacheService, ParameterInfo[] parameters, ServiceCacheAttribute svcCacheAttribute, string cacheKey)
        {
            invocation.Proceed();

            redisCacheService.AddNullableData(cacheKey, invocation.ReturnValue, svcCacheAttribute.TimeoutSecs);

            for (int i = 0; i < parameters.Length; i++)
            {
                if (parameters[i].ParameterType.IsByRef && invocation.Arguments[i] != null)
                {
                    redisCacheService.Add(cacheKey + parameters[i].Name, invocation.Arguments[i], svcCacheAttribute.TimeoutSecs);
                }
            }
        }
        public ICollection <Month> ParseCalendar(int year)
        {
            var _url = string.Format(_calendarSourceFormat, year);

            var document = _htmlParser.GetDocumentByUrl(_url);

            var htmlCalendars = document.DocumentNode.SelectNodes("//*[@class=\"cal\"]");

            var calendar = new List <Month>
            {
                new Month("Нулябрь", 0, year)
            };

            for (var i = 0; i < htmlCalendars.Count(); i++)
            {
                var htmlCalendar = htmlCalendars[i];

                var monthNode = htmlCalendar.SelectNodes($"{htmlCalendar.XPath}//th[@class=\"month\"]");

                var monthName = monthNode.Select(m => m.InnerText).FirstOrDefault();

                var monthNumber = i + 1;

                var month = new Month(monthName, monthNumber, year);

                month.Days.Add(new Day(0));

                calendar.Add(month);

                var days = htmlCalendar.SelectNodes($"{htmlCalendar.XPath}//td");

                foreach (var day in days)
                {
                    if (!int.TryParse(day.InnerText.Sanitize(), out var number))
                    {
                        _log.Warn($"Can't parse {day.InnerText} from {day.XPath}, {nameof(monthName)}={monthName}");

                        continue;
                    }

                    if (day.Attributes.Any(a => a.Name == "class" && a.Value == "inactively"))
                    {
                        continue;
                    }

                    var monthDay = new Day(number);

                    month.Days.Add(monthDay);

                    if (day.Attributes.Any(a => a.Name == "class" && a.Value == "preholiday"))
                    {
                        monthDay.Type = DayType.PreHoliday;

                        continue;
                    }

                    if (day.Attributes.Any(a => a.Name == "class" && a.Value.Contains("holiday weekend")))
                    {
                        monthDay.Type = DayType.NotWork;

                        continue;
                    }

                    if (day.Attributes.Any(a => a.Name == "class" && a.Value.Contains("weekend")))
                    {
                        monthDay.Type = DayType.Weekend;

                        continue;
                    }

                    if (day.Attributes.Any(a => a.Name == "class" && a.Value.Contains("nowork")))
                    {
                        monthDay.Type = DayType.SuddenNotWork;

                        continue;
                    }
                }

                var ranges = _rangeService.GetRanges(month);

                month.Ranges = ranges;
            }

            try
            {
                _cache.Add($"Calendar:{year}", calendar);
            }
            catch (Exception e)
            {
                _log.Error(e, $"Can't add calendar for {year}");
            }

            return(calendar);
        }