using System; using System.Linq; using BizHawk.Common.ReflectionExtensions; namespace BizHawk.Emulation.Common { /// /// injects services into other classes /// public static class ServiceInjector { /// /// clears all services from a target /// public static void ClearServices(object target) { Type targetType = target.GetType(); object[] tmp = new object[1]; foreach (var propinfo in targetType.GetPropertiesWithAttrib(typeof(RequiredService)) .Concat(targetType.GetPropertiesWithAttrib(typeof(OptionalService)))) { propinfo.GetSetMethod(true).Invoke(target, tmp); } } /// /// Feeds the target its required services. /// /// false if update failed public static bool UpdateServices(IEmulatorServiceProvider source, object target) { Type targetType = target.GetType(); object[] tmp = new object[1]; foreach (var propinfo in targetType.GetPropertiesWithAttrib(typeof(RequiredService))) { tmp[0] = source.GetService(propinfo.PropertyType); if (tmp[0] == null) return false; propinfo.GetSetMethod(true).Invoke(target, tmp); } foreach (var propinfo in targetType.GetPropertiesWithAttrib(typeof(OptionalService))) { tmp[0] = source.GetService(propinfo.PropertyType); propinfo.GetSetMethod(true).Invoke(target, tmp); } return true; } /// /// Determines whether a target is available, considering its dependencies /// and the services provided by the emulator core. /// public static bool IsAvailable(IEmulatorServiceProvider source, Type targetType) { return targetType.GetPropertiesWithAttrib(typeof(RequiredService)) .Select(pi => pi.PropertyType) .All(t => source.HasService(t)); } } [AttributeUsage(AttributeTargets.Property)] public class RequiredService : Attribute { } [AttributeUsage(AttributeTargets.Property)] public class OptionalService : Attribute { } }