mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-08 09:38:25 -05:00
* 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
122 lines
4.9 KiB
C#
122 lines
4.9 KiB
C#
//
|
|
// 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>();
|
|
}
|
|
}
|
|
}
|