public App() { System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; /* * .net core (and .net 5) changed the way assembly and type resolving work. * Preferred way to implement "plugins" is using custom AssemblyLoadContext per plugin * however, current Prism implementation is not AssemblyLoadContext friendly * Therefore this workaround make assembly loading work more or less like in .net framework * All assemblies are loaded to the default context and any type can be found via Type.GetType() * * The disadvantage is that assemblies cannot conflict with each other. If using AssemblyLoadContext * there would be no problem with for instance different versions of a package. */ Dictionary <string, string> assemblyToRequesting = new(); string?executingAssemblyLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { if (args.Name.EndsWith("resources") || args.RequestingAssembly == null) { return(null); } AssemblyName?name = new(args.Name); string?requestingAssemblyPath = executingAssemblyLocation + "/" + args.RequestingAssembly.GetName().Name + ".dll"; if (!File.Exists(requestingAssemblyPath)) { if (!assemblyToRequesting.TryGetValue(args.RequestingAssembly.GetName().Name ?? "", out requestingAssemblyPath)) { return(null); } } assemblyToRequesting.Add(name.Name ?? "", requestingAssemblyPath); AssemblyDependencyResolver?dependencyPathResolver = new(requestingAssemblyPath); string?path = dependencyPathResolver.ResolveAssemblyToPath(name); if (path == null) { return(null); } if (AssemblyLoadContext.Default.Assemblies.FirstOrDefault(t => t.GetName() == name) != null) { return(AssemblyLoadContext.Default.Assemblies.FirstOrDefault(t => t.GetName() == name)); } return(AssemblyLoadContext.Default.LoadFromAssemblyPath(path)); }; if (ProgramBootstrap.TryLaunchUpdaterIfNeeded()) { Current.Shutdown(); } }
// Initialization code. Don't use any Avalonia, third-party APIs or any // SynchronizationContext-reliant code before AppMain is called: things aren't initialized // yet and stuff might break. public static void Main(string[] args) { FixCurrentDirectory(); if (ProgramBootstrap.TryLaunchUpdaterIfNeeded()) { return; } System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; var app = BuildAvaloniaApp(); try { app.StartWithClassicDesktopLifetime(args); } catch (Exception e) { FatalErrorHandler.ExceptionOccured(e); } }
// Initialization code. Don't use any Avalonia, third-party APIs or any // SynchronizationContext-reliant code before AppMain is called: things aren't initialized // yet and stuff might break. public static void Main(string[] args) { FixCurrentDirectory(); if (ProgramBootstrap.TryLaunchUpdaterIfNeeded()) { return; } System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; SafeFireAndForgetExtensions.SetDefaultExceptionHandling(Console.WriteLine); GlobalApplication.Arguments.Init(args); var app = BuildAvaloniaApp(); try { app.StartWithClassicDesktopLifetime(args); } catch (Exception e) { FatalErrorHandler.ExceptionOccured(e); } }