diff --git a/src/Main/Base/Project/Src/Editor/IEditorControlService.cs b/src/Main/Base/Project/Src/Editor/IEditorControlService.cs
index e0f4f6a4ec..c3988c790e 100644
--- a/src/Main/Base/Project/Src/Editor/IEditorControlService.cs
+++ b/src/Main/Base/Project/Src/Editor/IEditorControlService.cs
@@ -11,7 +11,7 @@ namespace ICSharpCode.SharpDevelop.Editor
///
/// Allows creating new text editor instances and accessing the default text editor options.
///
- [FallbackService(typeof(EditorControlServiceFallback))]
+ [SDService(FallbackImplementation = typeof(EditorControlServiceFallback))]
public interface IEditorControlService
{
ITextEditor CreateEditor(out object control);
diff --git a/src/Main/Base/Project/Src/Gui/IWorkbench.cs b/src/Main/Base/Project/Src/Gui/IWorkbench.cs
index ad3fde8d74..195624dc22 100644
--- a/src/Main/Base/Project/Src/Gui/IWorkbench.cs
+++ b/src/Main/Base/Project/Src/Gui/IWorkbench.cs
@@ -14,6 +14,7 @@ namespace ICSharpCode.SharpDevelop.Gui
///
/// This is the basic interface to the workspace.
///
+ [SDService]
public interface IWorkbench : IMementoCapable
{
///
diff --git a/src/Main/Base/Project/Src/Services/File/IFileService.cs b/src/Main/Base/Project/Src/Services/File/IFileService.cs
index 2d894e2be6..1ea7131955 100644
--- a/src/Main/Base/Project/Src/Services/File/IFileService.cs
+++ b/src/Main/Base/Project/Src/Services/File/IFileService.cs
@@ -15,6 +15,7 @@ namespace ICSharpCode.SharpDevelop
///
/// File service.
///
+ [SDService]
public interface IFileService
{
#region Options
diff --git a/src/Main/Base/Project/Src/Services/IMessageLoop.cs b/src/Main/Base/Project/Src/Services/IMessageLoop.cs
index d8d30ff565..59e2a2b737 100644
--- a/src/Main/Base/Project/Src/Services/IMessageLoop.cs
+++ b/src/Main/Base/Project/Src/Services/IMessageLoop.cs
@@ -7,11 +7,14 @@ using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
+using ICSharpCode.Core;
+
namespace ICSharpCode.SharpDevelop
{
///
/// Represents a thread running a message loop.
///
+ [SDService]
public interface IMessageLoop
{
///
diff --git a/src/Main/Base/Project/Src/Services/ParserService/IAssemblyParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/IAssemblyParserService.cs
index 27536c9498..e882bdc69b 100644
--- a/src/Main/Base/Project/Src/Services/ParserService/IAssemblyParserService.cs
+++ b/src/Main/Base/Project/Src/Services/ParserService/IAssemblyParserService.cs
@@ -13,6 +13,7 @@ namespace ICSharpCode.SharpDevelop.Parser
///
/// Portions of parser service that deal with loading external assemblies for code completion.
///
+ [SDService]
public interface IAssemblyParserService
{
IUnresolvedAssembly GetAssembly(FileName fileName, CancellationToken cancellationToken = default(CancellationToken));
diff --git a/src/Main/Base/Project/Src/Services/ParserService/IGlobalAssemblyCacheService.cs b/src/Main/Base/Project/Src/Services/ParserService/IGlobalAssemblyCacheService.cs
index 5efb31ec9a..4bc44ea98d 100644
--- a/src/Main/Base/Project/Src/Services/ParserService/IGlobalAssemblyCacheService.cs
+++ b/src/Main/Base/Project/Src/Services/ParserService/IGlobalAssemblyCacheService.cs
@@ -3,12 +3,14 @@
using System;
using System.Collections.Generic;
+using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Parser
{
///
/// Interface for global assembly cache service.
///
+ [SDService]
public interface IGlobalAssemblyCacheService
{
///
diff --git a/src/Main/Base/Project/Src/Services/ParserService/IParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/IParserService.cs
index 291e8613c0..9eb9792413 100644
--- a/src/Main/Base/Project/Src/Services/ParserService/IParserService.cs
+++ b/src/Main/Base/Project/Src/Services/ParserService/IParserService.cs
@@ -21,6 +21,7 @@ namespace ICSharpCode.SharpDevelop.Parser
///
/// Manages parse runs and caches ParseInformation.
///
+ [SDService]
public interface IParserService
{
///
diff --git a/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs b/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs
index eb18f13094..fdbe5fa8ff 100644
--- a/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs
+++ b/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs
@@ -11,6 +11,7 @@ using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Gui
{
+ [SDService]
public interface IStatusBarService
{
//bool Visible { get; set; }
diff --git a/src/Main/Core/Project/ICSharpCode.Core.csproj b/src/Main/Core/Project/ICSharpCode.Core.csproj
index 1b451d42ae..8cd95ff779 100644
--- a/src/Main/Core/Project/ICSharpCode.Core.csproj
+++ b/src/Main/Core/Project/ICSharpCode.Core.csproj
@@ -107,7 +107,7 @@
-
+
diff --git a/src/Main/Core/Project/Src/AddInTree/IAddInTree.cs b/src/Main/Core/Project/Src/AddInTree/IAddInTree.cs
index 3c8b0a0dc3..b33956e3b2 100644
--- a/src/Main/Core/Project/Src/AddInTree/IAddInTree.cs
+++ b/src/Main/Core/Project/Src/AddInTree/IAddInTree.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
namespace ICSharpCode.Core
{
+ [SDService]
public interface IAddInTree
{
///
diff --git a/src/Main/Core/Project/Src/Services/AnalyticsMonitorService.cs b/src/Main/Core/Project/Src/Services/AnalyticsMonitorService.cs
index d3a33cb9cd..8f0412a9a2 100644
--- a/src/Main/Core/Project/Src/Services/AnalyticsMonitorService.cs
+++ b/src/Main/Core/Project/Src/Services/AnalyticsMonitorService.cs
@@ -9,7 +9,7 @@ namespace ICSharpCode.Core
/// Interface for AnalyticsMonitorService.
///
/// Implementations of this interface must be thread-safe.
- [FallbackService(typeof(AnalyticsMonitorFallback))]
+ [SDService(FallbackImplementation = typeof(AnalyticsMonitorFallback))]
public interface IAnalyticsMonitor
{
///
diff --git a/src/Main/Core/Project/Src/Services/ApplicationStateInfoService.cs b/src/Main/Core/Project/Src/Services/ApplicationStateInfoService.cs
index d22e3aa538..afa21d0134 100644
--- a/src/Main/Core/Project/Src/Services/ApplicationStateInfoService.cs
+++ b/src/Main/Core/Project/Src/Services/ApplicationStateInfoService.cs
@@ -12,6 +12,7 @@ namespace ICSharpCode.Core
/// This service is used to summarize important information
/// about the state of the application when an exception occurs.
///
+ [SDService]
public class ApplicationStateInfoService
{
readonly Dictionary> stateGetters = new Dictionary>(StringComparer.InvariantCulture);
diff --git a/src/Main/Core/Project/Src/Services/FallbackServiceAttribute.cs b/src/Main/Core/Project/Src/Services/FallbackServiceAttribute.cs
deleted file mode 100644
index 5ed53ee83f..0000000000
--- a/src/Main/Core/Project/Src/Services/FallbackServiceAttribute.cs
+++ /dev/null
@@ -1,62 +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.Collections.Generic;
-
-namespace ICSharpCode.Core
-{
- ///
- /// Used on a service interface to indicate the default implementation.
- ///
- [AttributeUsage(AttributeTargets.Interface, Inherited=false)]
- public class FallbackServiceAttribute : Attribute
- {
- readonly string assemblyQualifiedName;
- readonly Type fallbackServiceType;
-
- public FallbackServiceAttribute(Type fallbackServiceType)
- {
- if (fallbackServiceType == null)
- throw new ArgumentNullException("fallbackServiceType");
- this.fallbackServiceType = fallbackServiceType;
- }
-
- public FallbackServiceAttribute(string assemblyQualifiedName)
- {
- if (assemblyQualifiedName == null)
- throw new ArgumentNullException("assemblyQualifiedName");
- this.assemblyQualifiedName = assemblyQualifiedName;
- }
-
- public string AssemblyQualifiedName {
- get { return assemblyQualifiedName ?? fallbackServiceType.AssemblyQualifiedName; }
- }
-
- public Type FallbackServiceType {
- get { return fallbackServiceType ?? Type.GetType(assemblyQualifiedName); }
- }
- }
-
- sealed class FallbackServiceProvider : IServiceProvider
- {
- Dictionary fallbackServiceDict = new Dictionary();
-
- public object GetService(Type serviceType)
- {
- object instance;
- lock (fallbackServiceDict) {
- if (!fallbackServiceDict.TryGetValue(serviceType, out instance)) {
- var attr = serviceType.GetCustomAttributes(typeof(FallbackServiceAttribute), false);
- if (attr.Length == 1) {
- instance = Activator.CreateInstance(((FallbackServiceAttribute)attr[0]).FallbackServiceType);
- } else {
- instance = null;
- }
- fallbackServiceDict.Add(serviceType, instance);
- }
- }
- return instance;
- }
- }
-}
diff --git a/src/Main/Core/Project/Src/Services/LoggingService/ILoggingService.cs b/src/Main/Core/Project/Src/Services/LoggingService/ILoggingService.cs
index 45da07a668..1e416a9ec4 100644
--- a/src/Main/Core/Project/Src/Services/LoggingService/ILoggingService.cs
+++ b/src/Main/Core/Project/Src/Services/LoggingService/ILoggingService.cs
@@ -6,7 +6,7 @@ using ICSharpCode.Core.Implementation;
namespace ICSharpCode.Core
{
- [FallbackService(typeof(FallbackLoggingService))]
+ [SDService(FallbackImplementation = typeof(FallbackLoggingService))]
public interface ILoggingService
{
void Debug(object message);
diff --git a/src/Main/Core/Project/Src/Services/MessageService/IMessageService.cs b/src/Main/Core/Project/Src/Services/MessageService/IMessageService.cs
index b6a5c5c7e4..885ecbb0ce 100644
--- a/src/Main/Core/Project/Src/Services/MessageService/IMessageService.cs
+++ b/src/Main/Core/Project/Src/Services/MessageService/IMessageService.cs
@@ -9,7 +9,7 @@ namespace ICSharpCode.Core
///
/// Interface for the MessageService.
///
- [FallbackService(typeof(FallbackMessageService))]
+ [SDService(FallbackImplementation = typeof(FallbackMessageService))]
public interface IMessageService
{
///
diff --git a/src/Main/Core/Project/Src/Services/PropertyService/IPropertyService.cs b/src/Main/Core/Project/Src/Services/PropertyService/IPropertyService.cs
index 7a536c3e16..32f10f8d46 100644
--- a/src/Main/Core/Project/Src/Services/PropertyService/IPropertyService.cs
+++ b/src/Main/Core/Project/Src/Services/PropertyService/IPropertyService.cs
@@ -11,6 +11,7 @@ namespace ICSharpCode.Core
///
/// The property service.
///
+ [SDService]
public interface IPropertyService : INotifyPropertyChanged
{
///
diff --git a/src/Main/Core/Project/Src/Services/ResourceService/IResourceService.cs b/src/Main/Core/Project/Src/Services/ResourceService/IResourceService.cs
index a572e7cafa..53fe20ac52 100644
--- a/src/Main/Core/Project/Src/Services/ResourceService/IResourceService.cs
+++ b/src/Main/Core/Project/Src/Services/ResourceService/IResourceService.cs
@@ -10,7 +10,7 @@ namespace ICSharpCode.Core
///
/// Provides string and bitmap resources.
///
- [FallbackService(typeof(DummyResourceService))]
+ [SDService(FallbackImplementation = typeof(FallbackResourceService))]
public interface IResourceService
{
///
@@ -59,7 +59,7 @@ namespace ICSharpCode.Core
void RegisterNeutralImages(ResourceManager imageManager);
}
- sealed class DummyResourceService : IResourceService
+ sealed class FallbackResourceService : IResourceService
{
event EventHandler IResourceService.LanguageChanged { add {} remove {} }
diff --git a/src/Main/Core/Project/Src/Services/SDServiceAttribute.cs b/src/Main/Core/Project/Src/Services/SDServiceAttribute.cs
new file mode 100644
index 0000000000..d93f9c040d
--- /dev/null
+++ b/src/Main/Core/Project/Src/Services/SDServiceAttribute.cs
@@ -0,0 +1,52 @@
+// 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.Collections.Generic;
+
+namespace ICSharpCode.Core
+{
+ ///
+ /// Specifies that the interface is a SharpDevelop service that is accessible via SD.Services.
+ ///
+ ///
+ /// This attribute is mostly intended as documentation, so that it is easily possible to see
+ /// if a given service is globally available in SharpDevelop.
+ ///
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, Inherited=false)]
+ public class SDServiceAttribute : Attribute
+ {
+ ///
+ /// The class that implements the interface and serves as a fallback service
+ /// in case no real implementation is registered.
+ ///
+ ///
+ /// This property is also useful for unit tests, as there usually is no real service instance when testing.
+ ///
+ public Type FallbackImplementation { get; set; }
+ }
+
+ sealed class FallbackServiceProvider : IServiceProvider
+ {
+ Dictionary fallbackServiceDict = new Dictionary();
+
+ public object GetService(Type serviceType)
+ {
+ object instance;
+ lock (fallbackServiceDict) {
+ if (!fallbackServiceDict.TryGetValue(serviceType, out instance)) {
+ var attrs = serviceType.GetCustomAttributes(typeof(SDServiceAttribute), false);
+ if (attrs.Length == 1) {
+ var attr = (SDServiceAttribute)attrs[0];
+ if (attr.FallbackImplementation != null) {
+ instance = Activator.CreateInstance(attr.FallbackImplementation);
+ }
+ }
+ // store null if no fallback implementation exists
+ fallbackServiceDict.Add(serviceType, instance);
+ }
+ }
+ return instance;
+ }
+ }
+}