Привет!
Только собрался добавить, как увидел, что уже сделано
Пара мелких предложений:
1. Вместо uri.AbsolutePath использовать .LocalPath, он с учётом соглашений текущей ОС работает.
2. В сообщениях исключений указывать имена сборки/ресурса. Дико экономит время, особенно если всё, что до тебя дошло — это текст исключения.
3. В GetAssemblyDirectory
public static string GetAssemblyDirectory([NotNull] this Assembly assembly) =>
Path.GetDirectoryName(GetAssemblyPath(assembly)) ?? "";
возвращать результат как есть. На крайний случай — не пустую строку, а ".\"