127 lines
3.6 KiB
C#
Raw Normal View History

2023-05-22 15:09:00 -04:00
using Serilog;
using Splat;
2023-05-11 23:11:39 -04:00
using System.Collections.Generic;
using System.Linq;
namespace SPTInstaller.Helpers;
/// <summary>
/// A helper class to handle simple service registration to Splat with constructor parameter injection
/// </summary>
/// <remarks>Splat only recognizes the registered types and doesn't account for interfaces :(</remarks>
internal static class ServiceHelper
2023-05-11 23:11:39 -04:00
{
private static bool TryRegisterInstance<T, T2>(object[] parameters = null)
2023-05-11 23:11:39 -04:00
{
var instance = Activator.CreateInstance(typeof(T2), parameters);
if (instance != null)
2023-05-11 23:11:39 -04:00
{
Locator.CurrentMutable.RegisterConstant<T>((T)instance);
return true;
}
2023-05-11 23:11:39 -04:00
return false;
}
2023-05-11 23:11:39 -04:00
/// <summary>
/// Register a class as a service
/// </summary>
/// <typeparam name="T">class to register</typeparam>
public static void Register<T>() where T : class => Register<T, T>();
2023-05-11 23:11:39 -04:00
/// <summary>
/// Register a class as a service by another type
/// </summary>
/// <typeparam name="T">type to register as</typeparam>
/// <typeparam name="T2">class to register</typeparam>
public static void Register<T, T2>() where T : class
{
var constructors = typeof(T2).GetConstructors();
foreach(var constructor in constructors)
2023-05-11 23:11:39 -04:00
{
var parmesan = constructor.GetParameters();
2023-05-11 23:11:39 -04:00
if(parmesan.Length == 0)
2023-05-11 23:11:39 -04:00
{
if (TryRegisterInstance<T, T2>()) return;
2023-05-11 23:11:39 -04:00
continue;
}
2023-05-11 23:11:39 -04:00
List<object> parameters = new List<object>();
2023-05-11 23:11:39 -04:00
for(int i = 0; i < parmesan.Length; i++)
{
var parm = parmesan[i];
2023-05-11 23:11:39 -04:00
var parmValue = Get(parm.ParameterType);
2023-05-11 23:11:39 -04:00
if (parmValue != null) parameters.Add(parmValue);
2023-05-11 23:11:39 -04:00
}
if (TryRegisterInstance<T, T2>(parameters.ToArray())) return;
}
}
2023-05-11 23:11:39 -04:00
/// <summary>
/// Get a service from splat
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException">Thrown if the service isn't found</exception>
public static object Get(Type type)
{
var service = Locator.Current.GetService(type);
2023-05-11 23:11:39 -04:00
if (service == null)
{
var message = $"Could not locate service of type '{type.Name}'";
Log.Error(message);
throw new InvalidOperationException(message);
2023-05-11 23:11:39 -04:00
}
return service;
}
2023-05-11 23:11:39 -04:00
/// <summary>
/// Get a service from splat
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// <exception cref="InvalidOperationException">Thrown if the service isn't found</exception>
public static T Get<T>()
{
var service = Locator.Current.GetService<T>();
2023-05-11 23:11:39 -04:00
if (service == null)
{
var message = $"Could not locate service of type '{nameof(T)}'";
Log.Error(message);
throw new InvalidOperationException(message);
2023-05-11 23:11:39 -04:00
}
return service;
}
2023-05-11 23:11:39 -04:00
/// <summary>
/// Get all services of a type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// <exception cref="InvalidOperationException">thrown if no services are found</exception>
public static T[] GetAll<T>()
{
var services = Locator.Current.GetServices<T>().ToArray();
2023-05-11 23:11:39 -04:00
if (services == null || services.Count() == 0)
{
var message = $"Could not locate service of type '{nameof(T)}'";
Log.Error(message);
throw new InvalidOperationException(message);
2023-05-11 23:11:39 -04:00
}
return services;
2023-05-11 23:11:39 -04:00
}
}