mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-08 01:28:29 -05:00
Move unused forked code to external directory (#1192)
* Move unused forked code to external directory * Fix SLN build errors * Add back resource provider core since it's referenced by main resource provider project * Update PackageProjects step of pipeline
This commit is contained in:
44
external/Microsoft.SqlTools.Hosting.v2/Extensibility/ExportStandardMetadataAttribute.cs
vendored
Normal file
44
external/Microsoft.SqlTools.Hosting.v2/Extensibility/ExportStandardMetadataAttribute.cs
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Composition;
|
||||
|
||||
namespace Microsoft.SqlTools.Hosting.Extensibility
|
||||
{
|
||||
/// <summary>
|
||||
/// Base attribute class for all export definitions.
|
||||
/// </summary>
|
||||
[MetadataAttribute]
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public abstract class ExportStandardMetadataAttribute : ExportAttribute, IStandardMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for DAC extensibility exports
|
||||
/// </summary>
|
||||
protected ExportStandardMetadataAttribute(Type contractType, string id, string displayName = null)
|
||||
: base(contractType)
|
||||
{
|
||||
Id = id;
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The version of this extension
|
||||
/// </summary>
|
||||
public string Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The id of the extension
|
||||
/// </summary>
|
||||
public string Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The display name for the extension
|
||||
/// </summary>
|
||||
public virtual string DisplayName { get; }
|
||||
}
|
||||
}
|
||||
170
external/Microsoft.SqlTools.Hosting.v2/Extensibility/ExtensionServiceProvider.cs
vendored
Normal file
170
external/Microsoft.SqlTools.Hosting.v2/Extensibility/ExtensionServiceProvider.cs
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Composition.Convention;
|
||||
using System.Composition.Hosting;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using Microsoft.SqlTools.Hosting.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.Hosting.Extensibility
|
||||
{
|
||||
/// <summary>
|
||||
/// A MEF-based service provider. Supports any MEF-based configuration but is optimized for
|
||||
/// service discovery over a set of DLLs in an application scope. Any service registering using
|
||||
/// the <c>[Export(IServiceContract)]</c> attribute will be discovered and used by this service
|
||||
/// provider if it's in the set of Assemblies / Types specified during its construction. Manual
|
||||
/// override of this is supported by calling
|
||||
/// <see cref="RegisteredServiceProvider.RegisterSingleService" /> and similar methods, since
|
||||
/// this will initialize that service contract and avoid the MEF-based search and discovery
|
||||
/// process. This allows the service provider to link into existing singleton / known services
|
||||
/// while using MEF-based dependency injection and inversion of control for most of the code.
|
||||
/// </summary>
|
||||
public class ExtensionServiceProvider : RegisteredServiceProvider
|
||||
{
|
||||
private Func<ConventionBuilder, ContainerConfiguration> config;
|
||||
|
||||
public ExtensionServiceProvider(Func<ConventionBuilder, ContainerConfiguration> config)
|
||||
{
|
||||
Validate.IsNotNull(nameof(config), config);
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a service provider by loading a set of named assemblies, expected to be <paramref name="directory"/>
|
||||
/// </summary>
|
||||
/// <param name="directory">Directory to search for included assemblies</param>
|
||||
/// <param name="inclusionList">full DLL names, case insensitive, of assemblies to include</param>
|
||||
/// <returns><see cref="ExtensionServiceProvider"/> instance</returns>
|
||||
public static ExtensionServiceProvider CreateFromAssembliesInDirectory(string directory, IList<string> inclusionList)
|
||||
{
|
||||
//AssemblyLoadContext context = new AssemblyLoader(directory);
|
||||
var assemblyPaths = Directory.GetFiles(directory, "*.dll", SearchOption.TopDirectoryOnly);
|
||||
|
||||
List<Assembly> assemblies = new List<Assembly>();
|
||||
foreach (var path in assemblyPaths)
|
||||
{
|
||||
// skip DLL files not in inclusion list
|
||||
bool isInList = false;
|
||||
foreach (var item in inclusionList)
|
||||
{
|
||||
if (path.EndsWith(item, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
isInList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isInList)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
assemblies.Add(AssemblyLoadContext.Default.LoadFromAssemblyPath(path));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// we expect exceptions trying to scan all DLLs since directory contains native libraries
|
||||
}
|
||||
}
|
||||
|
||||
return Create(assemblies);
|
||||
}
|
||||
|
||||
public static ExtensionServiceProvider Create(IEnumerable<Assembly> assemblies)
|
||||
{
|
||||
Validate.IsNotNull(nameof(assemblies), assemblies);
|
||||
return new ExtensionServiceProvider(conventions => new ContainerConfiguration().WithAssemblies(assemblies, conventions));
|
||||
}
|
||||
|
||||
public static ExtensionServiceProvider Create(IEnumerable<Type> types)
|
||||
{
|
||||
Validate.IsNotNull(nameof(types), types);
|
||||
return new ExtensionServiceProvider(conventions => new ContainerConfiguration().WithParts(types, conventions));
|
||||
}
|
||||
|
||||
protected override IEnumerable<T> GetServicesImpl<T>()
|
||||
{
|
||||
EnsureExtensionStoreRegistered<T>();
|
||||
return base.GetServicesImpl<T>();
|
||||
}
|
||||
|
||||
private void EnsureExtensionStoreRegistered<T>()
|
||||
{
|
||||
if (!services.ContainsKey(typeof(T)))
|
||||
{
|
||||
ExtensionStore store = new ExtensionStore(typeof(T), config);
|
||||
Register(() => store.GetExports<T>());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merges in new assemblies to the existing container configuration.
|
||||
/// </summary>
|
||||
public void AddAssembliesToConfiguration(IEnumerable<Assembly> assemblies)
|
||||
{
|
||||
Validate.IsNotNull(nameof(assemblies), assemblies);
|
||||
var previousConfig = config;
|
||||
this.config = conventions => {
|
||||
// Chain in the existing configuration function's result, then include additional
|
||||
// assemblies
|
||||
ContainerConfiguration containerConfig = previousConfig(conventions);
|
||||
return containerConfig.WithAssemblies(assemblies, conventions);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A store for MEF exports of a specific type. Provides basic wrapper functionality around MEF to standarize how
|
||||
/// we lookup types and return to callers.
|
||||
/// </summary>
|
||||
public class ExtensionStore
|
||||
{
|
||||
private readonly CompositionHost host;
|
||||
private IList exports;
|
||||
private readonly Type contractType;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the store with a type to lookup exports of, and a function that configures the
|
||||
/// lookup parameters.
|
||||
/// </summary>
|
||||
/// <param name="contractType">Type to use as a base for all extensions being looked up</param>
|
||||
/// <param name="configure">Function that returns the configuration to be used</param>
|
||||
public ExtensionStore(Type contractType, Func<ConventionBuilder, ContainerConfiguration> configure)
|
||||
{
|
||||
Validate.IsNotNull(nameof(contractType), contractType);
|
||||
Validate.IsNotNull(nameof(configure), configure);
|
||||
this.contractType = contractType;
|
||||
ConventionBuilder builder = GetExportBuilder();
|
||||
ContainerConfiguration config = configure(builder);
|
||||
host = config.CreateContainer();
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetExports<T>()
|
||||
{
|
||||
if (exports == null)
|
||||
{
|
||||
exports = host.GetExports(contractType).ToList();
|
||||
}
|
||||
return exports.Cast<T>();
|
||||
}
|
||||
|
||||
private ConventionBuilder GetExportBuilder()
|
||||
{
|
||||
// Define exports as matching a parent type, export as that parent type
|
||||
var builder = new ConventionBuilder();
|
||||
builder.ForTypesDerivedFrom(contractType).Export(exportConventionBuilder => exportConventionBuilder.AsContractType(contractType));
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
external/Microsoft.SqlTools.Hosting.v2/Extensibility/IComposableService.cs
vendored
Normal file
21
external/Microsoft.SqlTools.Hosting.v2/Extensibility/IComposableService.cs
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace Microsoft.SqlTools.Hosting.Extensibility
|
||||
{
|
||||
/// <summary>
|
||||
/// A Service that expects to lookup other services. Using this interface on an exported service
|
||||
/// will ensure the <see cref="SetServiceProvider(IMultiServiceProvider)"/> method is called during
|
||||
/// service initialization
|
||||
/// </summary>
|
||||
public interface IComposableService
|
||||
{
|
||||
/// <summary>
|
||||
/// Supports settings the service provider being used to initialize the service.
|
||||
/// This is useful to look up other services and use them in your own service.
|
||||
/// </summary>
|
||||
void SetServiceProvider(IMultiServiceProvider provider);
|
||||
}
|
||||
}
|
||||
107
external/Microsoft.SqlTools.Hosting.v2/Extensibility/IHostedService.cs
vendored
Normal file
107
external/Microsoft.SqlTools.Hosting.v2/Extensibility/IHostedService.cs
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.Hosting.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.Hosting.Extensibility
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a hosted service that communicates with external processes via
|
||||
/// messages passed over the <see cref="ServiceHost"/>. The service defines
|
||||
/// a standard initialization method where it can hook up to the host.
|
||||
/// </summary>
|
||||
public interface IHostedService
|
||||
{
|
||||
/// <summary>
|
||||
/// Callback to initialize this service
|
||||
/// </summary>
|
||||
/// <param name="serviceHost"><see cref="IServiceHost"/> which supports registering
|
||||
/// event handlers and other callbacks for messages passed to external callers</param>
|
||||
void InitializeService(IServiceHost serviceHost);
|
||||
|
||||
/// <summary>
|
||||
/// What is the service type that you wish to register?
|
||||
/// </summary>
|
||||
Type ServiceType { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base class for <see cref="IHostedService"/> implementations that handles defining the <see cref="ServiceType"/>
|
||||
/// being registered. This simplifies service registration. This also implements <see cref="IComposableService"/> which
|
||||
/// allows injection of the service provider for lookup of other services.
|
||||
///
|
||||
/// Extending classes should implement per below code example
|
||||
/// <code>
|
||||
/// [Export(typeof(IHostedService)]
|
||||
/// MyService : HostedService<MyService>
|
||||
/// {
|
||||
/// public override void InitializeService(IServiceHost serviceHost)
|
||||
/// {
|
||||
/// serviceHost.SetRequestHandler(MyRequest.Type, HandleMyRequest);
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type to be registered for lookup in the service provider</typeparam>
|
||||
public abstract class HostedService<T> : IHostedService, IComposableService
|
||||
{
|
||||
protected IMultiServiceProvider ServiceProvider { get; private set; }
|
||||
|
||||
public virtual void SetServiceProvider(IMultiServiceProvider provider)
|
||||
{
|
||||
ServiceProvider = provider;
|
||||
}
|
||||
|
||||
public Type ServiceType => typeof(T);
|
||||
|
||||
protected async Task<THandler> HandleRequestAsync<THandler>(
|
||||
Func<Task<THandler>> handler,
|
||||
RequestContext<THandler> requestContext,
|
||||
string requestType)
|
||||
{
|
||||
Logger.Write(TraceEventType.Verbose, requestType);
|
||||
|
||||
try
|
||||
{
|
||||
THandler result = await handler();
|
||||
requestContext.SendResult(result);
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
requestContext.SendError(ex.ToString());
|
||||
}
|
||||
return default(THandler);
|
||||
}
|
||||
protected async Task<THandler> HandleSyncRequestAsAsync<THandler>(
|
||||
Func<THandler> handler,
|
||||
RequestContext<THandler> requestContext,
|
||||
string requestType)
|
||||
{
|
||||
Logger.Write(TraceEventType.Verbose, requestType);
|
||||
return await Task.Factory.StartNew(() => {
|
||||
try
|
||||
{
|
||||
THandler result = handler();
|
||||
requestContext.SendResult(result);
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
requestContext.SendError(ex.ToString());
|
||||
}
|
||||
return default(THandler);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public abstract void InitializeService(IServiceHost serviceHost);
|
||||
|
||||
}
|
||||
}
|
||||
101
external/Microsoft.SqlTools.Hosting.v2/Extensibility/IMultiServiceProvider.cs
vendored
Normal file
101
external/Microsoft.SqlTools.Hosting.v2/Extensibility/IMultiServiceProvider.cs
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.SqlTools.Hosting.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.Hosting.Extensibility
|
||||
{
|
||||
public interface IMultiServiceProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a service of a specific type. It is expected that only 1 instance of this type will be
|
||||
/// available
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of service to be found</typeparam>
|
||||
/// <returns>Instance of T or null if not found</returns>
|
||||
/// <exception cref="InvalidOperationException">The input sequence contains more than one element.-or-The input sequence is empty.</exception>
|
||||
T GetService<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a service of a specific type. The first service matching the specified filter will be returned
|
||||
/// available
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of service to be found</typeparam>
|
||||
/// <param name="filter">Filter to use in </param>
|
||||
/// <returns>Instance of T or null if not found</returns>
|
||||
/// <exception cref="InvalidOperationException">The input sequence contains more than one element.-or-The input sequence is empty.</exception>
|
||||
T GetService<T>(Predicate<T> filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets multiple services of a given type
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns>An enumerable of matching services</returns>
|
||||
IEnumerable<T> GetServices<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets multiple services of a given type, where they match a filter
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<T> GetServices<T>(Predicate<T> filter);
|
||||
}
|
||||
|
||||
|
||||
public abstract class ServiceProviderBase : IMultiServiceProvider
|
||||
{
|
||||
|
||||
public T GetService<T>()
|
||||
{
|
||||
return GetServices<T>().SingleOrDefault();
|
||||
}
|
||||
|
||||
public T GetService<T>(Predicate<T> filter)
|
||||
{
|
||||
Validate.IsNotNull(nameof(filter), filter);
|
||||
return GetServices<T>().SingleOrDefault(t => filter(t));
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetServices<T>(Predicate<T> filter)
|
||||
{
|
||||
Validate.IsNotNull(nameof(filter), filter);
|
||||
return GetServices<T>().Where(t => filter(t));
|
||||
}
|
||||
|
||||
public virtual IEnumerable<T> GetServices<T>()
|
||||
{
|
||||
var services = GetServicesImpl<T>();
|
||||
if (services == null)
|
||||
{
|
||||
return Enumerable.Empty<T>();
|
||||
}
|
||||
|
||||
return services.Select(t =>
|
||||
{
|
||||
InitComposableService(t);
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
||||
private void InitComposableService<T>(T t)
|
||||
{
|
||||
IComposableService c = t as IComposableService;
|
||||
c?.SetServiceProvider(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all services using the build in implementation
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
protected abstract IEnumerable<T> GetServicesImpl<T>();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
28
external/Microsoft.SqlTools.Hosting.v2/Extensibility/IStandardMetadata.cs
vendored
Normal file
28
external/Microsoft.SqlTools.Hosting.v2/Extensibility/IStandardMetadata.cs
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace Microsoft.SqlTools.Hosting.Extensibility
|
||||
{
|
||||
/// <summary>
|
||||
/// Standard Metadata needed for extensions.
|
||||
/// </summary>
|
||||
public interface IStandardMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension version. Should be in the format "1.0.0.0" or similar
|
||||
/// </summary>
|
||||
string Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Unique Id used to identify the export.
|
||||
/// </summary>
|
||||
string Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional Display name describing the export type
|
||||
/// </summary>
|
||||
string DisplayName { get; }
|
||||
}
|
||||
}
|
||||
121
external/Microsoft.SqlTools.Hosting.v2/Extensibility/RegisteredServiceProvider.cs
vendored
Normal file
121
external/Microsoft.SqlTools.Hosting.v2/Extensibility/RegisteredServiceProvider.cs
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.SqlTools.Hosting.Utility;
|
||||
using Microsoft.SqlTools.Hosting.v2;
|
||||
|
||||
namespace Microsoft.SqlTools.Hosting.Extensibility
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A service provider implementation that allows registering of specific services
|
||||
/// </summary>
|
||||
public class RegisteredServiceProvider : ServiceProviderBase
|
||||
{
|
||||
public delegate IEnumerable ServiceLookup();
|
||||
|
||||
protected readonly Dictionary<Type, ServiceLookup> services = new Dictionary<Type, ServiceLookup>();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a singular service to be returned during lookup
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns>this provider, to simplify fluent declarations</returns>
|
||||
/// <exception cref="ArgumentNullException">If service is null</exception>
|
||||
/// <exception cref="InvalidOperationException">If an existing service is already registered</exception>
|
||||
public virtual RegisteredServiceProvider RegisterSingleService<T>(T service)
|
||||
{
|
||||
Validate.IsNotNull(nameof(service), service);
|
||||
ThrowIfAlreadyRegistered<T>();
|
||||
services.Add(typeof(T), () => service.AsSingleItemEnumerable());
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a singular service to be returned during lookup
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// Type or interface this service should be registed as. Any <see cref="IMultiServiceProvider.GetServices{T}"/> request
|
||||
/// for that type will return this service
|
||||
/// </param>
|
||||
/// <param name="service">service object to be added</param>
|
||||
/// <returns>this provider, to simplify fluent declarations</returns>
|
||||
/// <exception cref="ArgumentNullException">If service is null</exception>
|
||||
/// <exception cref="InvalidOperationException">If an existing service is already registered</exception>
|
||||
public virtual RegisteredServiceProvider RegisterSingleService(Type type, object service)
|
||||
{
|
||||
Validate.IsNotNull(nameof(type), type);
|
||||
Validate.IsNotNull(nameof(service), service);
|
||||
ThrowIfAlreadyRegistered(type);
|
||||
ThrowIfIncompatible(type, service);
|
||||
services.Add(type, service.AsSingleItemEnumerable);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a function that can look up multiple services
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns>this provider, to simplify fluent declarations</returns>
|
||||
/// <exception cref="ArgumentNullException">If <paramref name="serviceLookup"/> is null</exception>
|
||||
/// <exception cref="InvalidOperationException">If an existing service is already registered</exception>
|
||||
public virtual RegisteredServiceProvider Register<T>(Func<IEnumerable<T>> serviceLookup)
|
||||
{
|
||||
Validate.IsNotNull(nameof(serviceLookup), serviceLookup);
|
||||
ThrowIfAlreadyRegistered<T>();
|
||||
services.Add(typeof(T), () => serviceLookup());
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual void RegisterHostedServices()
|
||||
{
|
||||
// Register all hosted services the service provider for their requested service type.
|
||||
// This ensures that when searching for the ConnectionService (eg) you can get it
|
||||
// without searching for an IHosted service of type ConnectionService
|
||||
foreach (IHostedService service in GetServices<IHostedService>())
|
||||
{
|
||||
RegisterSingleService(service.ServiceType, service);
|
||||
}
|
||||
}
|
||||
|
||||
private void ThrowIfAlreadyRegistered<T>()
|
||||
{
|
||||
ThrowIfAlreadyRegistered(typeof(T));
|
||||
}
|
||||
|
||||
private void ThrowIfAlreadyRegistered(Type type)
|
||||
{
|
||||
if (services.ContainsKey(type))
|
||||
{
|
||||
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.ServiceAlreadyRegistered, type.Name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void ThrowIfIncompatible(Type type, object service)
|
||||
{
|
||||
if (!type.IsInstanceOfType(service))
|
||||
{
|
||||
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.ServiceNotOfExpectedType, service.GetType().Name, type.Name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override IEnumerable<T> GetServicesImpl<T>()
|
||||
{
|
||||
ServiceLookup serviceLookup;
|
||||
if (services.TryGetValue(typeof(T), out serviceLookup))
|
||||
{
|
||||
return serviceLookup().Cast<T>();
|
||||
}
|
||||
return Enumerable.Empty<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user