diff --git a/src/AddIns/Analysis/UnitTesting/Src/RunTestCommandContext.cs b/src/AddIns/Analysis/UnitTesting/Src/RunTestCommandContext.cs index 23f16cec3e..4e7ea06e68 100644 --- a/src/AddIns/Analysis/UnitTesting/Src/RunTestCommandContext.cs +++ b/src/AddIns/Analysis/UnitTesting/Src/RunTestCommandContext.cs @@ -3,6 +3,7 @@ using System; using ICSharpCode.Core.Services; +using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Project; @@ -19,7 +20,7 @@ namespace ICSharpCode.UnitTesting MessageViewCategory unitTestCategory = TestService.UnitTestMessageView; UnitTestMessageService messageService = new UnitTestMessageService(); UnitTestSaveAllFilesCommand saveAllFilesCommand = new UnitTestSaveAllFilesCommand(); - IStatusBarService statusBarService = WorkbenchSingleton.StatusBar; + IStatusBarService statusBarService = SD.StatusBar; public IRegisteredTestFrameworks RegisteredTestFrameworks { get { return testFrameworks; } diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 5a45ee3c88..5886060035 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -401,6 +401,7 @@ + @@ -796,7 +797,7 @@ - + diff --git a/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs b/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs index ad7d0e47cd..95efe4d240 100644 --- a/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs +++ b/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs @@ -54,6 +54,7 @@ namespace ICSharpCode.SharpDevelop.Gui } } + [Obsolete("Use SD.StatusBar instead")] public static IStatusBarService StatusBar { get { return workbench != null ? workbench.StatusBar : null; diff --git a/src/Main/Base/Project/Src/Services/SD.cs b/src/Main/Base/Project/Src/Services/SD.cs new file mode 100644 index 0000000000..7cd6e6e13f --- /dev/null +++ b/src/Main/Base/Project/Src/Services/SD.cs @@ -0,0 +1,71 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.ComponentModel.Design; +using ICSharpCode.Core; +using ICSharpCode.Core.Services; +using ICSharpCode.SharpDevelop.Gui; + +namespace ICSharpCode.SharpDevelop +{ + /// + /// Static entry point for retrieving SharpDevelop services. + /// + public static class SD + { + /// + /// Gets the main service container for SharpDevelop. + /// + public static IServiceContainer Services { + get { return GetRequiredService(); } + } + + /// + /// Gets a service. Returns null if service is not found. + /// + public static T GetService() where T : class + { + return ServiceManager.Instance.GetService(); + } + + /// + /// Gets a service. Returns null if service is not found. + /// + public static T GetRequiredService() where T : class + { + return ServiceManager.Instance.GetRequiredService(); + } + + /// + /// Gets the workbench. + /// + public static IWorkbench Workbench { + get { + var workbench = WorkbenchSingleton.Workbench; + if (workbench == null) + throw new ServiceNotFoundException("Workbench"); + return workbench; + } + } + + /// + /// Gets the status bar. + /// + public static IStatusBarService StatusBar { + get { return Workbench.StatusBar; } + } + + public static ILoggingService LoggingService { + get { return GetRequiredService(); } + } + + public static IMessageService MessageService { + get { return GetRequiredService(); } + } + + public static IAnalyticsMonitor AnalyticsMonitor { + get { return GetRequiredService(); } + } + } +} diff --git a/src/Main/Base/Project/Src/Util/ThreadSafeServiceContainer.cs b/src/Main/Base/Project/Src/Util/ThreadSafeServiceContainer.cs new file mode 100644 index 0000000000..eb51427c90 --- /dev/null +++ b/src/Main/Base/Project/Src/Util/ThreadSafeServiceContainer.cs @@ -0,0 +1,115 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.ComponentModel.Design; +using System.Linq; +using System.Collections.Generic; + +namespace ICSharpCode.SharpDevelop +{ + /// + /// A thread-safe service container class. + /// + public class ThreadSafeServiceContainer : IServiceProvider, IServiceContainer, IDisposable + { + Dictionary services = new Dictionary(); + + public ThreadSafeServiceContainer() + { + services.Add(typeof(ThreadSafeServiceContainer), this); + services.Add(typeof(IServiceContainer), this); + } + + public object GetOrCreateService(Type type, Func serviceCreator) + { + lock (services) { + object instance; + if (!services.TryGetValue(type, out instance)) { + instance = serviceCreator(); + services.Add(type, instance); + } + return instance; + } + } + + public void TryAddService(Type type, object instance) + { + lock (services) { + if (!services.ContainsKey(type)) + services.Add(type, instance); + } + } + + public object GetService(Type serviceType) + { + object instance; + lock (services) { + if (!services.TryGetValue(serviceType, out instance)) + return null; + } + ServiceCreatorCallback callback = instance as ServiceCreatorCallback; + if (callback == null) + return instance; + object newInstance = callback(this, serviceType); + lock (services) { + if (services.TryGetValue(serviceType, out instance) && ReferenceEquals(instance, callback)) { + services[serviceType] = newInstance; + return newInstance; + } + } + // concurrent modification while running the callback (most likely another thread ran the callback first): + IDisposable disposable = newInstance as IDisposable; + if (disposable != null) + disposable.Dispose(); + return GetService(serviceType); // retry + } + + public void Dispose() + { + IDisposable[] disposables; + lock (services) { + disposables = services.Values.OfType().ToArray(); + services.Clear(); + } + foreach (IDisposable disposable in disposables) + disposable.Dispose(); + } + + public void AddService(Type serviceType, object serviceInstance) + { + lock (services) { + services.Add(serviceType, serviceInstance); + } + } + + public void AddService(Type serviceType, object serviceInstance, bool promote) + { + AddService(serviceType, serviceInstance); + } + + public void AddService(Type serviceType, ServiceCreatorCallback callback) + { + lock (services) { + services.Add(serviceType, callback); + } + } + + public void AddService(Type serviceType, ServiceCreatorCallback callback, bool promote) + { + AddService(serviceType, callback); + } + + public void RemoveService(Type serviceType) + { + lock (services) { + services.Remove(serviceType); + } + } + + public void RemoveService(Type serviceType, bool promote) + { + RemoveService(serviceType); + } + } +} diff --git a/src/Main/Base/Project/Src/Util/ThreadSafeServiceProvider.cs b/src/Main/Base/Project/Src/Util/ThreadSafeServiceProvider.cs deleted file mode 100644 index aaa9b94a7f..0000000000 --- a/src/Main/Base/Project/Src/Util/ThreadSafeServiceProvider.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Linq; -using System.Collections.Generic; - -namespace ICSharpCode.SharpDevelop -{ - /// - /// A thread-safe service container class. - /// - public class ThreadSafeServiceContainer : IServiceProvider, IDisposable - { - Dictionary services = new Dictionary(); - - public ThreadSafeServiceContainer() - { - services.Add(typeof(ThreadSafeServiceContainer), this); - } - - public object GetOrCreateService(Type type, Func serviceCreator) - { - lock (services) { - object instance; - if (!services.TryGetValue(type, out instance)) { - instance = serviceCreator(); - services.Add(type, instance); - } - return instance; - } - } - - public void TryAddService(Type type, object instance) - { - lock (services) { - if (!services.ContainsKey(type)) - services.Add(type, instance); - } - } - - public object GetService(Type type) - { - lock (services) { - object instance; - if (services.TryGetValue(type, out instance)) - return instance; - else - return null; - } - } - - public void Dispose() - { - IDisposable[] disposables; - lock (services) { - disposables = services.Values.OfType().ToArray(); - services.Clear(); - } - foreach (IDisposable disposable in disposables) - disposable.Dispose(); - } - } -} diff --git a/src/Main/Base/Test/WebReferences/WebReferenceTests.cs b/src/Main/Base/Test/WebReferences/WebReferenceTests.cs index 0525b71424..b555b6f13e 100644 --- a/src/Main/Base/Test/WebReferences/WebReferenceTests.cs +++ b/src/Main/Base/Test/WebReferences/WebReferenceTests.cs @@ -2,7 +2,6 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using ICSharpCode.SharpDevelop; -using SD = ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Project; using NUnit.Framework; using System; @@ -13,6 +12,8 @@ using System.Web.Services.Discovery; namespace ICSharpCode.SharpDevelop.Tests.WebReferences { + using SD = ICSharpCode.SharpDevelop.Gui; + /// /// Tests the generated project items for a web reference. /// diff --git a/src/Main/Core/Project/Src/Services/ServiceManager.cs b/src/Main/Core/Project/Src/Services/ServiceManager.cs index c521c662f3..eb7ff3dd79 100644 --- a/src/Main/Core/Project/Src/Services/ServiceManager.cs +++ b/src/Main/Core/Project/Src/Services/ServiceManager.cs @@ -47,7 +47,7 @@ namespace ICSharpCode.Core.Services { object service = GetService(serviceType); if (service == null) - throw new ServiceNotFoundException(); + throw new ServiceNotFoundException(serviceType != null ? serviceType.FullName : "null"); return service; } @@ -76,8 +76,8 @@ namespace ICSharpCode.Core.Services sealed class DefaultServiceManager : ServiceManager { - static ILoggingService loggingService = new TextWriterLoggingService(new DebugTextWriter()); - static IMessageService messageService = new TextWriterMessageService(Console.Out); + readonly ILoggingService loggingService = new TextWriterLoggingService(new DebugTextWriter()); + readonly IMessageService messageService = new TextWriterMessageService(Console.Out); public override ILoggingService LoggingService { get { return loggingService; }