Здравствуйте господа форумчане!
Предыстория: В районе года назад я написал некоторого чат бота и одним из его классов является некий Profiller - статический класс, который при инициализации вытягивает некоторый набор данных из файлов и формирует список профилей каналов.
Как то так:
public static class Profiller
{
private static ConcurrentBag<ProfileChannel> profileChannels = new ConcurrentBag<ProfileChannel>();
static Profiller()
{
LoadProfiles();
}
private static void LoadProfiles()
{
Console.WriteLine(profileChannels != null);
Console.WriteLine(Directory.GetCurrentDirectory());
var filenames = Directory.GetFiles("./ProfileChannels/Commands");
filenames.ToList().ForEach(Console.WriteLine);
foreach (var item in filenames)
{
Console.WriteLine(Path.GetFileNameWithoutExtension(item));
profileChannels.Add(FileToProfileChannel(Path.GetFileNameWithoutExtension(item)));
}
}
private static ProfileChannel FileToProfileChannel(string channelname)
{
string[] buf;
if (channelname != Path.GetFileNameWithoutExtension(templateCommandsPath))
buf = File.ReadAllText($"./ProfileChannels/Commands/{channelname}.txt").Split(separator: new string[] { "\r\n" } , options: StringSplitOptions.RemoveEmptyEntries);
else
buf = File.ReadAllText($"./ProfileChannels/Commands/{channelname}.txt").Split(separator: new string[] { "\r\n" }, options: StringSplitOptions.RemoveEmptyEntries);
var dir = new Dictionary<string, int>();
foreach (var item in buf)
{
var m = StateReg.Match(item);
if (m.Success)
{
dir.Add(m.Groups["command"].Value, int.Parse(m.Groups["value"].Value));
}
}
string[] sub = File.Exists($"./ProfileChannels/SubAnswers/{channelname}.txt") ? File.ReadAllLines($"./ProfileChannels/SubAnswers/{channelname}.txt") : null;
if(sub == null)
{
File.Copy(templateSubAnswersPath, $"./ProfileChannels/SubAnswers/{channelname}.txt");
sub = File.ReadAllLines($"./ProfileChannels/SubAnswers/{channelname}.txt");
}
string[] resub = File.Exists($"./ProfileChannels/ResubAnswers/{channelname}.txt") ? File.ReadAllLines($"./ProfileChannels/ResubAnswers/{channelname}.txt") : null;
if(resub == null)
{
File.Copy(templateResubAnswersPath, $"./ProfileChannels/ResubAnswers/{channelname}.txt");
resub = File.ReadAllLines($"./ProfileChannels/ResubAnswers/{channelname}.txt");
}
string[] activities = File.Exists($"./ProfileChannels/Activities/{channelname}.txt") ? File.ReadAllLines($"./ProfileChannels/Activities/{channelname}.txt") : null;
if (activities == null)
{
File.Copy(templateActivitiesPath, $"./ProfileChannels/Activities/{channelname}.txt");
activities = File.ReadAllLines($"./ProfileChannels/Activities/{channelname}.txt");
}
Console.WriteLine("Dir: ");
foreach (var item in dir)
{
Console.WriteLine(item.Key + ":" + item.Value);
}
Console.WriteLine($"channelname: {channelname}");
Console.WriteLine("activities:");
activities.ToList().ForEach(Console.WriteLine);
return new ProfileChannel(channelname,activities,dir["vote"],dir["advert"],dir["vkid"],dir["djid"],dir["qupdate"],dir["counter"],dir["quote"],dir["moscowtime"],dir["help"],dir["members"],dir["mystat"],dir["toplist"],dir["streamertime"],dir["music"],dir["viewers"],dir["uptime"],dir["8ball"],dir["reconnect"],dir["discord"],dir["wakeup"],dir["sleep"]) { SubAnswers = sub?.ToList(), ResubAnswers = resub?.ToList() };
}
}
Под виндой это успешно работало в течение года и тут встала задача перенести этот ужас на сервер с ubuntu 16.04 lts.
Перенес все, настроил подключение и тп...
Собрал проект под .net core 2 на сервере(предварительно разумеется обновив все зависимости и тп.), в том числе протестировал это отдельно на виртуалке с Linux Mint 18.(Там все норм работает)
Теперь про ситуацию на новом сервере с ubuntu:
Есть некоторый класс Channel, где происходит первый вызов из статического класса:
if (Profiller.GetProfileOrDefault(Name) == null)
Profiller.TryCreateProfile(Name);
Итак, зная механику, любой скажет, что порядок вызова такой: static Profiller.Profiller static Profiller.GetProfileOrDefault(Name) ...
Но добавив в конструктор некоторый вывод, я убедился, что статический конструктор не был вызван. Как это понимать? Возможно у net core 2.0 под linux есть отличия при вызове статики? Поясните пожалуйста. Спасибо!
UPD: также стоит упомянуть, что методы из класс Profiller (не только эти методы) вызываются довольно часто
UPD: Добавил вывод перед 77 строкой
P.S Просьба не пинать за статический класс с большим кол-вом логики, я знаю что это 'дрянной стиль (еще бы кучу сингелтонов наплодил, дурак, скажите вы:)', но в данное время у меня нет желания вновь вспоминать, на чем все это завязано, со временем перепишу все с нуля.
Подведу итог, я ошибался, как и возможно, ТЫ читающий этот пост и думающий, что у тебя не вызывается конструктор:) Так что нормально все с конструкторами в net core, ищи ошибку у себя в коде, она точно есть :) Ошибка оказалась гораздо банальнее, чем думалось, ОСТОРОЖНЕЕ С ИСПОЛЬЗОВАНИЕМ \r\n для парсинга тестов, в линуксе \r работает не совсем так, гуглим, все.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
С# как преобразовывать подобные строковые значения string time1 = "2 ч 46 мин" и string time2 = "54 мин" в TimeSpan ?
Ребята мы должны использовать IComparer с типом точным? (не обобщенным) Или можем использовать и обобщенный?
Есть методВ этом методе должны кое-какие данные из основной программы, где этот метод и вызывается