aspnetcore/Microsoft.AspNet.CoreServices/ServiceProvider.cs

165 lines
5.7 KiB
C#

using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNet.CoreServices
{
/// <summary>
/// The default IServiceProvider.
/// </summary>
public class ServiceProvider : IServiceProvider
{
private readonly IDictionary<Type, Func<object>> _services = new Dictionary<Type, Func<object>>();
private readonly IDictionary<Type, List<Func<object>>> _priorServices = new Dictionary<Type, List<Func<object>>>();
/// <summary>
///
/// </summary>
public ServiceProvider()
{
_services[typeof(IServiceProvider)] = () => this;
}
/// <summary>
/// Gets the service object of the specified type.
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public virtual object GetService(Type serviceType)
{
return GetSingleService(serviceType) ?? GetMultiService(serviceType);
}
private object GetSingleService(Type serviceType)
{
Func<object> serviceFactory;
return _services.TryGetValue(serviceType, out serviceFactory)
? serviceFactory.Invoke()
: null;
}
private object GetMultiService(Type collectionType)
{
if (collectionType.GetTypeInfo().IsGenericType &&
collectionType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
Type serviceType = collectionType.GetTypeInfo().GenericTypeArguments.Single();
Type listType = typeof(List<>).MakeGenericType(serviceType);
var services = (IList)Activator.CreateInstance(listType);
Func<object> serviceFactory;
if (_services.TryGetValue(serviceType, out serviceFactory))
{
services.Add(serviceFactory());
List<Func<object>> prior;
if (_priorServices.TryGetValue(serviceType, out prior))
{
foreach (var factory in prior)
{
services.Add(factory());
}
}
}
return services;
}
return null;
}
/// <summary>
/// Remove all occurrences of the given type from the provider.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public virtual ServiceProvider RemoveAll<T>()
{
return RemoveAll(typeof(T));
}
/// <summary>
/// Remove all occurrences of the given type from the provider.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public virtual ServiceProvider RemoveAll(Type type)
{
_services.Remove(type);
_priorServices.Remove(type);
return this;
}
/// <summary>
/// Add an instance of type TService to the list of providers.
/// </summary>
/// <typeparam name="TService"></typeparam>
/// <param name="instance"></param>
/// <returns></returns>
public virtual ServiceProvider AddInstance<TService>(object instance)
{
return AddInstance(typeof(TService), instance);
}
/// <summary>
/// Add an instance of the given type to the list of providers.
/// </summary>
/// <param name="service"></param>
/// <param name="instance"></param>
/// <returns></returns>
public virtual ServiceProvider AddInstance(Type service, object instance)
{
return Add(service, () => instance);
}
/// <summary>
/// Specify that services of the type TService should be fulfilled by the type TImplementation.
/// </summary>
/// <typeparam name="TService"></typeparam>
/// <typeparam name="TImplementation"></typeparam>
/// <returns></returns>
public virtual ServiceProvider Add<TService, TImplementation>()
{
return Add(typeof(TService), typeof(TImplementation));
}
/// <summary>
/// Specify that services of the type serviceType should be fulfilled by the type implementationType.
/// </summary>
/// <param name="serviceType"></param>
/// <param name="implementationType"></param>
/// <returns></returns>
public virtual ServiceProvider Add(Type serviceType, Type implementationType)
{
Func<IServiceProvider, object> factory = ActivatorUtilities.CreateFactory(implementationType);
return Add(serviceType, () => factory(this));
}
/// <summary>
/// Specify that services of the given type should be created with the given serviceFactory.
/// </summary>
/// <param name="serviceType"></param>
/// <param name="serviceFactory"></param>
/// <returns></returns>
public virtual ServiceProvider Add(Type serviceType, Func<object> serviceFactory)
{
Func<object> existing;
if (_services.TryGetValue(serviceType, out existing))
{
List<Func<object>> prior;
if (_priorServices.TryGetValue(serviceType, out prior))
{
prior.Add(existing);
}
else
{
prior = new List<Func<object>> { existing };
_priorServices.Add(serviceType, prior);
}
}
_services[serviceType] = serviceFactory;
return this;
}
}
}