499 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			499 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C#
		
	
	
	
| 
								 | 
							
								// Disable unreachable code warning caused by DEBUG
							 | 
						|||
| 
								 | 
							
								#pragma warning disable 0162
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								namespace SRF.Service
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    using System;
							 | 
						|||
| 
								 | 
							
								    using System.Collections.Generic;
							 | 
						|||
| 
								 | 
							
								    using System.Linq;
							 | 
						|||
| 
								 | 
							
								    using System.Reflection;
							 | 
						|||
| 
								 | 
							
								    using Components;
							 | 
						|||
| 
								 | 
							
								    using Helpers;
							 | 
						|||
| 
								 | 
							
								    using Internal;
							 | 
						|||
| 
								 | 
							
								    using UnityEngine;
							 | 
						|||
| 
								 | 
							
								    using Object = UnityEngine.Object;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    [AddComponentMenu(ComponentMenuPaths.SRServiceManager)]
							 | 
						|||
| 
								 | 
							
								    public class SRServiceManager : SRAutoSingleton<SRServiceManager>
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								#if SRDEBUG
							 | 
						|||
| 
								 | 
							
										public const bool EnableLogging = true;
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
								        public const bool EnableLogging = false;
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#if (!UNITY_2017 && !UNITY_2018 && !UNITY_2019) || UNITY_2019_3_OR_NEWER
							 | 
						|||
| 
								 | 
							
								        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
							 | 
						|||
| 
								 | 
							
								        public static void RuntimeInitialize()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            // To handle entering play mode without a domain reload, need to reset the state of the service manager.
							 | 
						|||
| 
								 | 
							
								            _hasQuit = false;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Register the assembly that contains type <typeparamref name="TType"/> with the service manager.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        /// <typeparam name="TType"></typeparam>
							 | 
						|||
| 
								 | 
							
								        public static void RegisterAssembly<TType>()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								#if NETFX_CORE
							 | 
						|||
| 
								 | 
							
								            var assembly = typeof(TType).GetTypeInfo().Assembly;
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
								            var assembly = typeof(TType).Assembly;
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (_assemblies.Contains(assembly))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            _assemblies.Add(assembly);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Is there a service loading?
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public static bool IsLoading
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            get { return LoadingCount > 0; }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        public static int LoadingCount = 0;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        public static T GetService<T>() where T : class
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            var s = GetServiceInternal(typeof(T)) as T;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (s == null && (!_hasQuit || EnableLogging))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                Debug.LogWarning("Service {0} not found. (HasQuit: {1})".Fmt(typeof(T).Name, _hasQuit));
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return s;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        public static object GetService(Type t)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            var s = GetServiceInternal(t);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (s == null && (!_hasQuit || EnableLogging))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                Debug.LogWarning("Service {0} not found. (HasQuit: {1})".Fmt(t.Name, _hasQuit));
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return s;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static object GetServiceInternal(Type t)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (_hasQuit || !Application.isPlaying)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return null;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            var services = Instance._services;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            for (var i = 0; i < services.Count; i++)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                var s = services[i];
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (t.IsAssignableFrom(s.Type))
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    if (s.Object == null)
							 | 
						|||
| 
								 | 
							
								                    {
							 | 
						|||
| 
								 | 
							
								                        UnRegisterService(t);
							 | 
						|||
| 
								 | 
							
								                        break;
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                    return s.Object;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return Instance.AutoCreateService(t);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        public static bool HasService<T>() where T : class
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            return HasService(typeof(T));
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        public static bool HasService(Type t)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (_hasQuit || !Application.isPlaying)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return false;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            var services = Instance._services;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            for (var i = 0; i < services.Count; i++)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                var s = services[i];
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (t.IsAssignableFrom(s.Type))
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    return s.Object != null;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return false;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        public static void RegisterService<T>(object service) where T : class
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            RegisterService(typeof(T), service);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static void RegisterService(Type t, object service)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (_hasQuit)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (HasService(t))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (GetServiceInternal(t) == service)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    return;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                throw new Exception("Service already registered for type " + t.Name);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            UnRegisterService(t);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (!t.IsInstanceOfType(service))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                throw new ArgumentException("service {0} must be assignable from type {1}".Fmt(service.GetType(), t));
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            Instance._services.Add(new Service {
							 | 
						|||
| 
								 | 
							
								                Object = service,
							 | 
						|||
| 
								 | 
							
								                Type = t
							 | 
						|||
| 
								 | 
							
								            });
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        public static void UnRegisterService<T>() where T : class
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            UnRegisterService(typeof(T));
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static void UnRegisterService(Type t)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (_hasQuit || !HasInstance)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (!HasService(t))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            var services = Instance._services;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            for (var i = services.Count - 1; i >= 0; i--)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                var s = services[i];
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (s.Type == t)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    services.RemoveAt(i);
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        [Serializable]
							 | 
						|||
| 
								 | 
							
								        private class Service
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            public object Object;
							 | 
						|||
| 
								 | 
							
								            public Type Type;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        [Serializable]
							 | 
						|||
| 
								 | 
							
								        private class ServiceStub
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            public Func<object> Constructor;
							 | 
						|||
| 
								 | 
							
								            public Type InterfaceType;
							 | 
						|||
| 
								 | 
							
								            public Func<Type> Selector;
							 | 
						|||
| 
								 | 
							
								            public Type Type;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            public override string ToString()
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                var s = InterfaceType.Name + " (";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (Type != null)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    s += "Type: " + Type;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								                else if (Selector != null)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    s += "Selector: " + Selector;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								                else if (Constructor != null)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    s += "Constructor: " + Constructor;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                s += ")";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                return s;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static readonly List<Assembly> _assemblies = new List<Assembly>(2);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private readonly SRList<Service> _services = new SRList<Service>();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private List<ServiceStub> _serviceStubs;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static bool _hasQuit;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        protected override void Awake()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            _hasQuit = false;
							 | 
						|||
| 
								 | 
							
								            base.Awake();
							 | 
						|||
| 
								 | 
							
								            DontDestroyOnLoad(CachedGameObject);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            CachedGameObject.hideFlags = HideFlags.NotEditable;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        protected void UpdateStubs()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (_serviceStubs != null)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            RegisterAssembly<SRServiceManager>();
							 | 
						|||
| 
								 | 
							
								          
							 | 
						|||
| 
								 | 
							
								            _serviceStubs = new List<ServiceStub>();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            var types = new List<Type>();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            foreach (var assembly in _assemblies)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                try
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								#if NETFX_CORE
							 | 
						|||
| 
								 | 
							
								                    types.AddRange(assembly.ExportedTypes);
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
								                    types.AddRange(assembly.GetExportedTypes());
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								                catch (Exception e)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    Debug.LogError("[SRServiceManager] Error loading assembly {0}".Fmt(assembly.FullName), this);
							 | 
						|||
| 
								 | 
							
								                    Debug.LogException(e);
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            foreach (var type in types)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                ScanType(type);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (EnableLogging)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                var serviceStrings =
							 | 
						|||
| 
								 | 
							
								                    _serviceStubs.Select(p => "	{0}".Fmt(p)).ToArray();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                Debug.Log("[SRServiceManager] Services Discovered: {0} \n  {1}".Fmt(serviceStrings.Length,
							 | 
						|||
| 
								 | 
							
								                    string.Join("\n  ", serviceStrings)));
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        protected object AutoCreateService(Type t)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            UpdateStubs();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            foreach (var stub in _serviceStubs)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (stub.InterfaceType != t)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                object service = null;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (stub.Constructor != null)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    service = stub.Constructor();
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								                else
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    var serviceType = stub.Type;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                    if (serviceType == null)
							 | 
						|||
| 
								 | 
							
								                    {
							 | 
						|||
| 
								 | 
							
								                        serviceType = stub.Selector();
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                    service = DefaultServiceConstructor(t, serviceType);
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (!HasService(t))
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    RegisterService(t, service);
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (EnableLogging)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    Debug.Log("[SRServiceManager] Auto-created service: {0} ({1})".Fmt(stub.Type, stub.InterfaceType),
							 | 
						|||
| 
								 | 
							
								                        service as Object);
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                return service;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return null;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        protected void OnApplicationQuit()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            _hasQuit = true;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static object DefaultServiceConstructor(Type serviceIntType, Type implType)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            // If mono-behaviour based, create a gameobject for this service
							 | 
						|||
| 
								 | 
							
								            if (typeof(MonoBehaviour).IsAssignableFrom(implType))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                var go = new GameObject("_S_" + serviceIntType.Name);
							 | 
						|||
| 
								 | 
							
								                return go.AddComponent(implType);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // If ScriptableObject based, create an instance
							 | 
						|||
| 
								 | 
							
								            if (typeof(ScriptableObject).IsAssignableFrom(implType))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                var obj = ScriptableObject.CreateInstance(implType);
							 | 
						|||
| 
								 | 
							
								                return obj;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // If just a standard C# object, just create an instance
							 | 
						|||
| 
								 | 
							
								            return Activator.CreateInstance(implType);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#region Type Scanning
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private void ScanType(Type type)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            var attribute = SRReflection.GetAttribute<ServiceAttribute>(type);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (attribute != null)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                _serviceStubs.Add(new ServiceStub {
							 | 
						|||
| 
								 | 
							
								                    Type = type,
							 | 
						|||
| 
								 | 
							
								                    InterfaceType = attribute.ServiceType
							 | 
						|||
| 
								 | 
							
								                });
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            ScanTypeForConstructors(type, _serviceStubs);
							 | 
						|||
| 
								 | 
							
								            ScanTypeForSelectors(type, _serviceStubs);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static void ScanTypeForSelectors(Type t, List<ServiceStub> stubs)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            var methods = GetStaticMethods(t);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            foreach (var method in methods)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                var attrib = SRReflection.GetAttribute<ServiceSelectorAttribute>(method);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (attrib == null)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (method.ReturnType != typeof(Type))
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    Debug.LogError("ServiceSelector must have return type of Type ({0}.{1}())".Fmt(t.Name, method.Name));
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (method.GetParameters().Length > 0)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    Debug.LogError("ServiceSelector must have no parameters ({0}.{1}())".Fmt(t.Name, method.Name));
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                var stub = stubs.FirstOrDefault(p => p.InterfaceType == attrib.ServiceType);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (stub == null)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    stub = new ServiceStub {
							 | 
						|||
| 
								 | 
							
								                        InterfaceType = attrib.ServiceType
							 | 
						|||
| 
								 | 
							
								                    };
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                    stubs.Add(stub);
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#if NETFX_CORE
							 | 
						|||
| 
								 | 
							
								                stub.Selector = (Func<Type>)method.CreateDelegate(typeof(Func<Type>));
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
								                stub.Selector = (Func<Type>)Delegate.CreateDelegate(typeof(Func<Type>), method);
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static void ScanTypeForConstructors(Type t, List<ServiceStub> stubs)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            var methods = GetStaticMethods(t);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            foreach (var method in methods)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                var attrib = SRReflection.GetAttribute<ServiceConstructorAttribute>(method);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (attrib == null)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (method.ReturnType != attrib.ServiceType)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    Debug.LogError("ServiceConstructor must have return type of {2} ({0}.{1}())".Fmt(t.Name, method.Name,
							 | 
						|||
| 
								 | 
							
								                        attrib.ServiceType));
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (method.GetParameters().Length > 0)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    Debug.LogError("ServiceConstructor must have no parameters ({0}.{1}())".Fmt(t.Name, method.Name));
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                var stub = stubs.FirstOrDefault(p => p.InterfaceType == attrib.ServiceType);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (stub == null)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    stub = new ServiceStub {
							 | 
						|||
| 
								 | 
							
								                        InterfaceType = attrib.ServiceType
							 | 
						|||
| 
								 | 
							
								                    };
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                    stubs.Add(stub);
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                var m = method;
							 | 
						|||
| 
								 | 
							
								                stub.Constructor = () => m.Invoke(null, null);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#endregion
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#region Reflection
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static MethodInfo[] GetStaticMethods(Type t)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								#if !NETFX_CORE
							 | 
						|||
| 
								 | 
							
								            return t.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
							 | 
						|||
| 
								 | 
							
								#else
							 | 
						|||
| 
								 | 
							
								            return t.GetTypeInfo().DeclaredMethods.Where(p => p.IsStatic).ToArray();
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#endregion
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 |