using System; using System.Collections.Generic; using System.Linq; namespace BizHawk.Emulation.Common { /// /// A generic implementation of IEmulatorService provider that provides /// this functionality to any core. /// The provider will scan an IEmulator and register all IEmulatorServices /// that the core object itself implements. In addition it provides /// a Register() method to allow the core to pass in any additional services /// /// public class BasicServiceProvider : IEmulatorServiceProvider { private readonly Dictionary _services = new Dictionary(); public BasicServiceProvider(IEmulator core) { // simplified logic here doesn't scan for possible services; just adds what it knows is implemented by the core // this removes the possibility of automagically picking up a service in a nested class, (find the type, then // find the field), but we're going to keep such logic out of the basic provider. anything the passed // core doesn't implement directly needs to be added with Register() // this also fully allows services that are not IEmulatorService Type coreType = core.GetType(); var services = coreType.GetInterfaces() .Where(t => typeof(IEmulatorService).IsAssignableFrom(t)) .Where(t => t != typeof(IEmulatorService)); foreach (Type service in services) { _services.Add(service, core); } // add the actual instantiated type and any types in the hierarchy // except for object because that would be dumb (or would it?) while (coreType != typeof(object)) { _services.Add(coreType, core); coreType = coreType.BaseType; } } /// the core can call this to register an additional service /// The to register /// is null public void Register(T provider) where T : IEmulatorService { if (provider == null) { throw new ArgumentNullException(nameof(provider)); } _services[typeof(T)] = provider; } public T GetService() where T : IEmulatorService { return (T)GetService(typeof(T)); } public object GetService(Type t) { if (_services.TryGetValue(t, out var service)) { return service; } return null; } public bool HasService() where T : IEmulatorService { return HasService(typeof(T)); } public bool HasService(Type t) { return _services.ContainsKey(t); } public IEnumerable AvailableServices =>_services.Select(d => d.Key); } }