From 4c7d0ebb26dfb109dd3afd43b38b3b5954bdda01 Mon Sep 17 00:00:00 2001 From: Hendrik Mennen Date: Thu, 17 Sep 2026 12:36:54 +0200 Subject: [PATCH] update onnxruntime --- Directory.Build.props | 2 +- src/OneWare.Core/App.axaml.cs | 8 +- .../Services/OnnxRuntimeBootstrapper.cs | 160 ++++++++++++++++-- .../Services/OnnxRuntimeService.cs | 67 +++++++- .../Installers/OnnxRuntimePackageInstaller.cs | 6 +- .../PackageManagerModule.cs | 69 +++++--- 6 files changed, 269 insertions(+), 43 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index e5e23b398..2f950b53c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 1.23.2 + 1.28.0 diff --git a/src/OneWare.Core/App.axaml.cs b/src/OneWare.Core/App.axaml.cs index 418af9c1b..79f4b5fb2 100644 --- a/src/OneWare.Core/App.axaml.cs +++ b/src/OneWare.Core/App.axaml.cs @@ -156,8 +156,10 @@ protected virtual AvaloniaObject CreateShell() settingsService.RegisterSettingCategory("Languages", 0, "FluentIcons.ProofreadLanguageRegular"); + var onnxRuntimeOptions = OnnxRuntimeBootstrapper.GetOnnxRuntimeOptions(paths); + settingsService.RegisterSetting("Tools", "ONNX Runtime", OnnxRuntimeBootstrapper.SettingSelectedRuntimeKey, - new ComboBoxSetting("Runtime (restart required)", "onnxruntime-builtin", OnnxRuntimeBootstrapper.GetOnnxRuntimeOptions(paths).Cast().ToArray()) + new ComboBoxSetting("Runtime (restart required)", "onnxruntime-builtin", onnxRuntimeOptions.Cast().ToArray()) { MarkdownDocumentation = """ **This setting requires a restart to be effective** @@ -168,6 +170,10 @@ protected virtual AvaloniaObject CreateShell() """ }); + // The selected runtime can be uninstalled or removed as unsupported between sessions. + if (!onnxRuntimeOptions.Contains(settingsService.GetSettingValue(OnnxRuntimeBootstrapper.SettingSelectedRuntimeKey))) + settingsService.SetSettingValue(OnnxRuntimeBootstrapper.SettingSelectedRuntimeKey, "onnxruntime-builtin"); + var onnxRuntimeBootstrapper = Services.Resolve(); var selectedRuntime = settingsService.GetSettingValue(OnnxRuntimeBootstrapper.SettingSelectedRuntimeKey); var initialExecutionProviders = onnxRuntimeBootstrapper.GetOnnxExecutionProviders(selectedRuntime); diff --git a/src/OneWare.Core/Services/OnnxRuntimeBootstrapper.cs b/src/OneWare.Core/Services/OnnxRuntimeBootstrapper.cs index 1c4b53fa9..3e0b1fa1e 100644 --- a/src/OneWare.Core/Services/OnnxRuntimeBootstrapper.cs +++ b/src/OneWare.Core/Services/OnnxRuntimeBootstrapper.cs @@ -2,6 +2,7 @@ using System.Reflection; using System.Text.Json; using Microsoft.Extensions.Logging; +using Microsoft.ML.OnnxRuntime; using OneWare.Essentials.Enums; using OneWare.Essentials.Helpers; using OneWare.Essentials.Services; @@ -16,6 +17,41 @@ public class OnnxRuntimeBootstrapper public const string SettingOpenVinoDeviceKey = "OnnxRuntime_OpenVinoDevice"; + /// + /// Runtimes from the frozen combined-build packages. They ship an onnxruntime older than the + /// managed assembly, which is not ABI compatible, and were superseded by Windows ML and the + /// plugin execution providers. Stale installations are removed instead of being loaded. + /// + private static readonly string[] LegacyIncompatibleRuntimes = + [ + "onnxruntime-directml", + "onnxruntime-openvino", + "onnxruntime-qnn" + ]; + + /// + /// Native libraries that live next to onnxruntime and are loaded dynamically by it at runtime. + /// They are preloaded by absolute path so the OS loader resolves them from the side-loaded + /// runtime directory instead of the application directory. + /// + private static readonly string[] SiblingDependencyLibraries = + [ + "onnxruntime_providers_shared", + "DirectML", + "Microsoft.Windows.AI.MachineLearning" + ]; + + /// + /// Plugin execution providers are additive: they do not replace onnxruntime itself but are + /// registered against it via . + /// Maps the plugin library base name to its ONNX Runtime registration name. + /// + private static readonly (string LibraryBaseName, string RegistrationName)[] PluginExecutionProviders = + [ + ("onnxruntime_providers_openvino_plugin", "OpenVINOExecutionProvider"), + ("onnxruntime_providers_qnn", "QNNExecutionProvider") + ]; + private readonly ILogger _logger; private readonly IPaths _paths; private static readonly Lock ResolverSync = new(); @@ -25,6 +61,17 @@ public class OnnxRuntimeBootstrapper public string SelectedRuntime { get; private set; } = "onnxruntime-builtin"; + /// + /// ONNX Runtime registration name of the side-loaded plugin execution provider, if the selected + /// runtime is a plugin execution provider rather than a full runtime. + /// + public string? PluginExecutionProviderName { get; private set; } + + /// + /// Absolute path to the side-loaded plugin execution provider library. + /// + public string? PluginExecutionProviderLibraryPath { get; private set; } + public OnnxRuntimeBootstrapper(IPaths paths, ILogger logger) { _paths = paths; @@ -40,7 +87,8 @@ public static string[] GetOnnxRuntimeOptions(IPaths paths) options.AddRange(Directory.GetDirectories(paths.OnnxRuntimesDirectory) .Select(Path.GetFileName) .Where(x => !string.IsNullOrWhiteSpace(x))! - .Cast()); + .Cast() + .Where(x => !LegacyIncompatibleRuntimes.Contains(x, StringComparer.OrdinalIgnoreCase))); } catch { @@ -66,17 +114,17 @@ public OnnxExecutionProvider[] GetOnnxExecutionProviders(string? runtimeName) if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) executionProviders.Add(OnnxExecutionProvider.CoreMl); break; - case "onnxruntime-directml": + case "onnxruntime-windowsml": executionProviders.Add(OnnxExecutionProvider.DirectMl); break; case "onnxruntime-nvidia": executionProviders.Add(OnnxExecutionProvider.Cuda); executionProviders.Add(OnnxExecutionProvider.TensorRt); break; - case "onnxruntime-openvino": + case "onnxruntime-ep-openvino": executionProviders.Add(OnnxExecutionProvider.OpenVino); break; - case "onnxruntime-qnn": + case "onnxruntime-ep-qnn": executionProviders.Add(OnnxExecutionProvider.Qnn); break; } @@ -92,7 +140,18 @@ public void Initialize() { // We don't use settings service here because it is not loaded at this state var selectedRuntime = ReadStringSetting(SettingSelectedRuntimeKey)?.Trim() ?? "no-runtime"; - + + RemoveLegacyRuntimes(); + + if (LegacyIncompatibleRuntimes.Contains(selectedRuntime, StringComparer.OrdinalIgnoreCase)) + { + _logger.LogWarning( + "ONNX runtime '{Runtime}' is no longer supported and was removed. Falling back to the built-in runtime.", + selectedRuntime); + SelectedRuntime = "onnxruntime-builtin"; + return; + } + var selectedRuntimeRoot = Path.Combine(_paths.OnnxRuntimesDirectory, selectedRuntime); var runtimeRootToLoad = CreateSessionRuntimeCopy(selectedRuntime, selectedRuntimeRoot) ?? selectedRuntimeRoot; @@ -120,6 +179,29 @@ public void Initialize() } } + /// + /// Deletes installations of runtimes that are no longer ABI compatible with the bundled managed + /// assembly, so they cannot be side-loaded and no longer show up as a selectable runtime. + /// + private void RemoveLegacyRuntimes() + { + foreach (var legacyRuntime in LegacyIncompatibleRuntimes) + { + var path = Path.Combine(_paths.OnnxRuntimesDirectory, legacyRuntime); + if (!Directory.Exists(path)) continue; + + try + { + Directory.Delete(path, true); + _logger.LogInformation("Removed unsupported ONNX runtime '{Runtime}'.", legacyRuntime); + } + catch (Exception ex) + { + _logger.LogDebug(ex, "Failed to remove unsupported ONNX runtime '{Runtime}'.", legacyRuntime); + } + } + } + private string? CreateSessionRuntimeCopy(string runtimeName, string sourceRootPath) { if (string.IsNullOrWhiteSpace(runtimeName) || !Directory.Exists(sourceRootPath)) @@ -157,15 +239,9 @@ private bool TryLoadFromNativeDirectory(string nativeDirectory) { if (!Directory.Exists(nativeDirectory)) return false; - var fileNames = GetOnnxRuntimeFileNameCandidates(); - var providersShared = PlatformHelper.GetLibraryFileName("onnxruntime_providers_shared"); - - // Ensure provider shared library can be resolved before loading onnxruntime itself. - var providerSharedPath = Path.Combine(nativeDirectory, providersShared); - if (File.Exists(providerSharedPath)) - _ = NativeLibrary.TryLoad(providerSharedPath, out _); + PreloadSiblingDependencies(nativeDirectory); - foreach (var fileName in fileNames.Distinct(StringComparer.OrdinalIgnoreCase)) + foreach (var fileName in GetOnnxRuntimeFileNameCandidates().Distinct(StringComparer.OrdinalIgnoreCase)) { var fullPath = Path.Combine(nativeDirectory, fileName); if (!File.Exists(fullPath)) continue; @@ -177,9 +253,64 @@ private bool TryLoadFromNativeDirectory(string nativeDirectory) return true; } + return TryDetectPluginExecutionProvider(nativeDirectory); + } + + /// + /// Detects a plugin execution provider in the given directory. Plugin providers ship without + /// onnxruntime itself and are registered against the active runtime once ONNX Runtime is + /// initialized, so nothing is loaded here beyond recording the library path. + /// + private bool TryDetectPluginExecutionProvider(string nativeDirectory) + { + foreach (var (libraryBaseName, registrationName) in PluginExecutionProviders) + { + foreach (var candidate in BuildLibraryFileCandidates(libraryBaseName)) + { + var fullPath = Path.Combine(nativeDirectory, candidate); + if (!File.Exists(fullPath)) continue; + + PluginExecutionProviderName = registrationName; + PluginExecutionProviderLibraryPath = fullPath; + + // Preloading by absolute path lets the loader resolve the provider's own dependencies + // (OpenVINO/QNN runtime libraries) from the side-loaded directory. + if (!NativeLibrary.TryLoad(fullPath, out _)) + _logger.LogDebug("Failed to preload plugin execution provider '{Path}'.", fullPath); + + _logger.LogInformation("Found ONNX Runtime plugin execution provider {Provider} at {Path}", + registrationName, fullPath); + return true; + } + } + return false; } + /// + /// Preloads native libraries that sit next to onnxruntime and are resolved dynamically by it. + /// Loading them by absolute path first makes the loader reuse the already loaded module instead + /// of searching the application directory, where the side-loaded copies do not exist. + /// + private void PreloadSiblingDependencies(string nativeDirectory) + { + foreach (var libraryBaseName in SiblingDependencyLibraries) + { + // Not using BuildLibraryFileCandidates: names like "Microsoft.Windows.AI.MachineLearning" + // already contain dots and would be treated as having a file extension. + var platformFileName = PlatformHelper.GetLibraryFileName(libraryBaseName); + + foreach (var candidate in new[] { platformFileName, $"lib{platformFileName}" }) + { + var fullPath = Path.Combine(nativeDirectory, candidate); + if (!File.Exists(fullPath)) continue; + + if (!NativeLibrary.TryLoad(fullPath, out _)) + _logger.LogDebug("Failed to preload ONNX Runtime dependency '{Path}'.", fullPath); + } + } + } + private IEnumerable EnumerateNativeSearchDirectories(string rootPath) { var directories = new List(); @@ -240,6 +371,9 @@ private void ConfigureOnnxRuntimeDllImportResolver(string? nativeDirectory, IntP try { + // Our resolver takes over native lookup, so ONNX Runtime must not install its own. + OrtEnv.DisableDllImportResolver = true; + var onnxAssembly = typeof(Microsoft.ML.OnnxRuntime.InferenceSession).Assembly; NativeLibrary.SetDllImportResolver(onnxAssembly, ResolveOnnxRuntimeNativeLibrary); _onnxResolverRegistered = true; diff --git a/src/OneWare.Core/Services/OnnxRuntimeService.cs b/src/OneWare.Core/Services/OnnxRuntimeService.cs index 76a93fa63..12b3c5c81 100644 --- a/src/OneWare.Core/Services/OnnxRuntimeService.cs +++ b/src/OneWare.Core/Services/OnnxRuntimeService.cs @@ -12,6 +12,9 @@ public class OnnxRuntimeService : IOnnxRuntimeService private readonly ISettingsService _settingsService; private readonly OnnxRuntimeBootstrapper _bootstrapper; private readonly ILogger _logger; + private readonly Lock _pluginRegistrationSync = new(); + private bool _pluginRegistrationAttempted; + private bool _pluginRegistered; public OnnxRuntimeService(OnnxRuntimeBootstrapper bootstrapper, ILogger logger, ISettingsService settingsService) { @@ -110,7 +113,15 @@ public SessionOptions CreateSessionOptions(OnnxExecutionProvider? providerOverri break; case OnnxExecutionProvider.OpenVino: - so.AppendExecutionProvider_OpenVINO(GetOpenVinoDevice()); + if (!TryAppendPluginExecutionProvider(so, "OpenVINOExecutionProvider", + new Dictionary { ["device_type"] = GetOpenVinoDevice() })) + so.AppendExecutionProvider_OpenVINO(GetOpenVinoDevice()); + break; + + case OnnxExecutionProvider.Qnn: + if (!TryAppendPluginExecutionProvider(so, "QNNExecutionProvider", + new Dictionary())) + so.AppendExecutionProvider("QNN"); break; } } @@ -124,6 +135,60 @@ public SessionOptions CreateSessionOptions(OnnxExecutionProvider? providerOverri return so; } + /// + /// Registers a side-loaded plugin execution provider with ONNX Runtime and appends the devices it + /// exposes to the session options. Plugin providers replaced the frozen combined-build packages + /// (OpenVINO, QNN) and are additive to the active runtime. + /// + private bool TryAppendPluginExecutionProvider(SessionOptions sessionOptions, string providerName, + Dictionary providerOptions) + { + if (!string.Equals(_bootstrapper.PluginExecutionProviderName, providerName, StringComparison.Ordinal)) + return false; + + if (!EnsurePluginExecutionProviderRegistered()) return false; + + var env = OrtEnv.Instance(); + var devices = env.GetEpDevices() + .Where(x => string.Equals(x.EpName, providerName, StringComparison.Ordinal)) + .ToArray(); + + if (devices.Length == 0) + { + _logger.LogWarning("Plugin execution provider '{Provider}' did not expose any devices.", providerName); + return false; + } + + sessionOptions.AppendExecutionProvider(env, devices, providerOptions); + return true; + } + + private bool EnsurePluginExecutionProviderRegistered() + { + lock (_pluginRegistrationSync) + { + if (_pluginRegistrationAttempted) return _pluginRegistered; + _pluginRegistrationAttempted = true; + + var name = _bootstrapper.PluginExecutionProviderName; + var path = _bootstrapper.PluginExecutionProviderLibraryPath; + if (name == null || path == null) return false; + + try + { + OrtEnv.Instance().RegisterExecutionProviderLibrary(name, path); + _pluginRegistered = true; + _logger.LogInformation("Registered ONNX Runtime plugin execution provider '{Provider}'.", name); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to register ONNX Runtime plugin execution provider '{Provider}'.", name); + } + + return _pluginRegistered; + } + } + private string GetOpenVinoDevice() { var configuredDevice = _settingsService diff --git a/src/OneWare.PackageManager/Installers/OnnxRuntimePackageInstaller.cs b/src/OneWare.PackageManager/Installers/OnnxRuntimePackageInstaller.cs index 5175eb590..3084ca448 100644 --- a/src/OneWare.PackageManager/Installers/OnnxRuntimePackageInstaller.cs +++ b/src/OneWare.PackageManager/Installers/OnnxRuntimePackageInstaller.cs @@ -25,9 +25,9 @@ public override Task InstallAsync(PackageInstallContext var recommendedExecutionProvider = runtime switch { "onnxruntime-nvidia" => OnnxExecutionProvider.Cuda, - "onnxruntime-directml" => OnnxExecutionProvider.DirectMl, - "onnxruntime-openvino" => OnnxExecutionProvider.OpenVino, - "onnxruntime-qnn" => OnnxExecutionProvider.Qnn, + "onnxruntime-windowsml" => OnnxExecutionProvider.DirectMl, + "onnxruntime-ep-openvino" => OnnxExecutionProvider.OpenVino, + "onnxruntime-ep-qnn" => OnnxExecutionProvider.Qnn, _ => OnnxExecutionProvider.Cpu }; settingsService.SetSettingValue("OnnxRuntime_SelectedExecutionProvider", recommendedExecutionProvider); diff --git a/src/OneWare.PackageManager/PackageManagerModule.cs b/src/OneWare.PackageManager/PackageManagerModule.cs index fec610e45..d1920a218 100644 --- a/src/OneWare.PackageManager/PackageManagerModule.cs +++ b/src/OneWare.PackageManager/PackageManagerModule.cs @@ -50,31 +50,31 @@ public class PackageManagerModule : OneWareModuleBase [ new PackageVersion { - Version = "1.23.2", + Version = "1.28.0", Targets = [ new PackageTarget { Target = "linux-x64", - Url = "https://www.nuget.org/api/v2/package/Microsoft.ML.OnnxRuntime.Gpu.Linux/1.23.2" + Url = "https://www.nuget.org/api/v2/package/Microsoft.ML.OnnxRuntime.Gpu.Linux/1.28.0" }, new PackageTarget { Target = "win-x64", - Url = "https://www.nuget.org/api/v2/package/Microsoft.ML.OnnxRuntime.Gpu.Windows/1.23.2" + Url = "https://www.nuget.org/api/v2/package/Microsoft.ML.OnnxRuntime.Gpu.Windows/1.28.0" }, ] } ] }; - public static readonly Package OnnxRuntimeDirectMlPackage = new() + public static readonly Package OnnxRuntimeWindowsMlPackage = new() { Category = "ONNX Runtimes", - Id = "onnxruntime-directml", + Id = "onnxruntime-windowsml", Type = "OnnxRuntime", - Name = "ONNX Runtime DirectML", - Description = "ONNX Runtime with DirectML for Windows", + Name = "ONNX Runtime Windows ML", + Description = "Windows ML runtime with DirectML GPU acceleration for Windows", License = "MIT", IconUrl = "https://raw.githubusercontent.com/hendrikmennen/SAM3-TENSORRT-PYTHON/refs/heads/main/ORT_icon_for_light_bg.png", Links = @@ -82,12 +82,12 @@ public class PackageManagerModule : OneWareModuleBase new PackageLink { Name = "NuGet", - Url = "https://www.nuget.org/packages/Microsoft.ML.OnnxRuntime.DirectML/1.23.0" + Url = "https://www.nuget.org/packages/Microsoft.Windows.AI.MachineLearning" }, new PackageLink { Name = "GitHub", - Url = "https://github.com/microsoft/onnxruntime" + Url = "https://github.com/microsoft/windowsml" } ], Tabs = @@ -102,18 +102,19 @@ public class PackageManagerModule : OneWareModuleBase [ new PackageVersion { - Version = "1.23.0", + // Windows ML 2.5.77-rc bundles ONNX Runtime 1.28.0, matching OnnxRuntimeVersion. + Version = "2.5.77-rc", Targets = [ new PackageTarget { Target = "win-x64", - Url = "https://www.nuget.org/api/v2/package/Microsoft.ML.OnnxRuntime.DirectML/1.23.0" + Url = "https://www.nuget.org/api/v2/package/Microsoft.Windows.AI.MachineLearning/2.5.77-rc" }, new PackageTarget { Target = "win-arm64", - Url = "https://www.nuget.org/api/v2/package/Microsoft.ML.OnnxRuntime.DirectML/1.23.0" + Url = "https://www.nuget.org/api/v2/package/Microsoft.Windows.AI.MachineLearning/2.5.77-rc" } ] } @@ -123,14 +124,19 @@ public class PackageManagerModule : OneWareModuleBase public static readonly Package OnnxRuntimeOpenVinoPackage = new() { Category = "ONNX Runtimes", - Id = "onnxruntime-openvino", + Id = "onnxruntime-ep-openvino", Type = "OnnxRuntime", Name = "ONNX Runtime OpenVINO", - Description = "ONNX Runtime with OpenVINO execution provider", + Description = "OpenVINO execution provider plugin for Intel CPUs, GPUs and NPUs", License = "MIT", IconUrl = "https://raw.githubusercontent.com/hendrikmennen/SAM3-TENSORRT-PYTHON/refs/heads/main/ORT_icon_for_light_bg.png", Links = [ + new PackageLink + { + Name = "NuGet", + Url = "https://www.nuget.org/packages/Intel.ML.OnnxRuntime.EP.OpenVINO" + }, new PackageLink { Name = "GitHub", @@ -149,13 +155,18 @@ public class PackageManagerModule : OneWareModuleBase [ new PackageVersion { - Version = "1.23.0", + Version = "1.7.0", Targets = [ new PackageTarget { Target = "win-x64", - Url = "https://www.nuget.org/api/v2/package/Intel.ML.OnnxRuntime.OpenVino/1.23.0" + Url = "https://www.nuget.org/api/v2/package/Intel.ML.OnnxRuntime.EP.OpenVINO/1.7.0" + }, + new PackageTarget + { + Target = "linux-x64", + Url = "https://www.nuget.org/api/v2/package/Intel.ML.OnnxRuntime.EP.OpenVINO/1.7.0" } ] } @@ -165,18 +176,23 @@ public class PackageManagerModule : OneWareModuleBase public static readonly Package OnnxRuntimeQnnPackage = new() { Category = "ONNX Runtimes", - Id = "onnxruntime-qnn", + Id = "onnxruntime-ep-qnn", Type = "OnnxRuntime", Name = "ONNX Runtime QNN", - Description = "ONNX Runtime with Qualcomm QNN execution provider", + Description = "Qualcomm QNN execution provider plugin for Snapdragon NPUs", License = "MIT", IconUrl = "https://raw.githubusercontent.com/hendrikmennen/SAM3-TENSORRT-PYTHON/refs/heads/main/ORT_icon_for_light_bg.png", Links = [ + new PackageLink + { + Name = "NuGet", + Url = "https://www.nuget.org/packages/Qualcomm.ML.OnnxRuntime.QNN" + }, new PackageLink { Name = "GitHub", - Url = "https://github.com/microsoft/onnxruntime" + Url = "https://github.com/onnxruntime/onnxruntime-qnn" } ], Tabs = @@ -191,13 +207,18 @@ public class PackageManagerModule : OneWareModuleBase [ new PackageVersion { - Version = "1.23.2", + Version = "2.6.0", Targets = [ new PackageTarget { Target = "win-arm64", - Url = "https://www.nuget.org/api/v2/package/Microsoft.ML.OnnxRuntime.QNN/1.23.2" + Url = "https://www.nuget.org/api/v2/package/Qualcomm.ML.OnnxRuntime.QNN/2.6.0" + }, + new PackageTarget + { + Target = "win-x64", + Url = "https://www.nuget.org/api/v2/package/Qualcomm.ML.OnnxRuntime.QNN/2.6.0" } ] } @@ -235,12 +256,12 @@ public override void Initialize(IServiceProvider serviceProvider) packageService.RegisterPackage(OnnxRuntimeNvidiaPackage); if(PlatformHelper.Platform is PlatformId.WinX64 or PlatformId.WinArm64) - packageService.RegisterPackage(OnnxRuntimeDirectMlPackage); + packageService.RegisterPackage(OnnxRuntimeWindowsMlPackage); - if(PlatformHelper.Platform is PlatformId.WinX64) + if(PlatformHelper.Platform is PlatformId.WinX64 or PlatformId.LinuxX64) packageService.RegisterPackage(OnnxRuntimeOpenVinoPackage); - if(PlatformHelper.Platform is PlatformId.WinArm64) + if(PlatformHelper.Platform is PlatformId.WinX64 or PlatformId.WinArm64) packageService.RegisterPackage(OnnxRuntimeQnnPackage); var windowService = serviceProvider.Resolve();