csharp/abist-co-ltd/hololens-opencv-laserpointer/Assets/MRTK/SDK/Experimental/ServiceManagers/Support/Scripts/BaseServiceManager.cs

BaseServiceManager.cs
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Microsoft.MixedReality.Toolkit.Utilities;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace Microsoft.MixedReality.Toolkit.Experimental
{
    /// 
    /// Base clast providing service registration and management functionality. This clast can be used to implement a
    /// custom service management component for one or more services, similar to the MixedRealityToolkit object.
    /// 
    [AddComponentMenu("Scripts/MRTK/SDK/BaseServiceManager")]
    public clast BaseServiceManager : MonoBehaviour, IMixedRealityServiceRegistrar
    {
        /// 
        /// The collection of registered services.
        /// 
        protected Dictionary registeredServices = new Dictionary();

        #region MonoBehaviour implementation

        protected virtual void Update()
        {
            if (Application.isPlaying)
            {
                foreach (IMixedRealityService service in registeredServices.Values)
                {
                    service.Update();
                }
            }
        }

        private void LateUpdate()
        {
            if (Application.isPlaying)
            {
                if (Application.isPlaying)
                {
                    foreach (IMixedRealityService service in registeredServices.Values)
                    {
                        service.LateUpdate();
                    }
                }
            }
        }


        protected virtual void OnEnable()
        {
            if (Application.isPlaying)
            {
                foreach (IMixedRealityService service in registeredServices.Values)
                {
                    service.Enable();
                }
            }
        }

        protected virtual void OnDisable()
        {
            if (Application.isPlaying)
            {
                foreach (IMixedRealityService service in registeredServices.Values)
                {
                    service.Disable();
                }
            }
        }

        protected virtual void OnDestroy()
        {
            foreach (IMixedRealityService service in registeredServices.Values)
            {
                service.Disable(); // Disable before destroy to ensure the service has time to get in a good state.
                service.Destroy();
            }
            registeredServices.Clear();
        }

        #endregion MonoBehaviour implementation

        #region IMixedRealityServiceRegistrar implementation

        /// 
        public T GetService(string name = null, bool showLogs = true) where T : IMixedRealityService
        {
            T serviceInstance = FindService(name);

            if (showLogs && (serviceInstance == null))
            {
                Debug.LogError($"Failed to get the requested service of type {typeof(T)}.");
            }

            return serviceInstance;
        }

        /// 
        public IReadOnlyList GetServices(string name = null) where T : IMixedRealityService
        {
            Type interfaceType = typeof(T);
            List matchingServices = new List();

            foreach(IMixedRealityService service in registeredServices.Values)
            {
                if (!interfaceType.IsastignableFrom(service.GetType())) { continue; }

                // If a name has been provided and if it matches the services's name, add the service.
                if (!string.IsNullOrWhiteSpace(name) && string.Equals(service.Name, name))
                {
                    matchingServices.Add((T)service);
                }
                // If no name has been specified, always add the service.
                else
                {
                    matchingServices.Add((T)service);
                }
            }

            return matchingServices;
        }

        /// 
        public bool IsServiceRegistered(string name = null) where T : IMixedRealityService
        {
            return (GetService(name) != null);
        }

        /// 
        public bool RegisterService(T serviceInstance) where T : IMixedRealityService
        {
            Type interfaceType = typeof(T);

            if (registeredServices.ContainsKey(interfaceType))
            {
                Debug.LogError($"Failed to register {serviceInstance} service. There is already a registered service implementing {interfaceType}");
                return false;
            }

            bool registered = MixedRealityServiceRegistry.AddService(serviceInstance, this);
            if (registered)
            {
                registeredServices.Add(interfaceType, serviceInstance);
            }

            return registered;
        }

        /// 
        public bool RegisterService(Type concreteType, SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1), params object[] args) where T : IMixedRealityService
        {
            T serviceInstance = ActivateInstance(concreteType, supportedPlatforms, args);

            if (serviceInstance == null)
            {
                return false;
            }

            return RegisterService(serviceInstance);
        }

        /// 
        public bool UnregisterService(string name = null) where T : IMixedRealityService
        {
            T serviceInstance = FindService(name);

            if (serviceInstance == null) { return false; }

            return UnregisterService(serviceInstance);
        }

        /// 
        public bool UnregisterService(T serviceInstance) where T : IMixedRealityService
        {
            if (serviceInstance == null) { return false; }

            Type interfaceType = typeof(T);
            if (!registeredServices.ContainsKey(interfaceType)) { return false; }

            registeredServices.Remove(interfaceType);
            return MixedRealityServiceRegistry.RemoveService(serviceInstance, this);
        }

        /// 
        /// Activates an instance of the specified concrete type using the provided argument collection.
        /// 
        /// The interface which must be implemented by the concrete type.
        /// The type of object to be instantiated.
        /// The platform(s) on which the concrete type is supported.
        /// Collection of arguments to provide to the concrete type's constructor.
        /// An instance of the concrete type. Returns a default value of T (typically null) in the event of a failure.
        private T ActivateInstance(Type concreteType, SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1), params object[] args) where T : IMixedRealityService
        {
            if (concreteType == null) { return default(T); }

#if UNITY_EDITOR
            if (!UnityEditor.EditorUserBuildSettings.activeBuildTarget.IsPlatformSupported(supportedPlatforms))
#else
            if (!Application.platform.IsPlatformSupported(supportedPlatforms))
#endif
            {
                return default(T);
            }

            if (!typeof(T).IsastignableFrom(concreteType))
            {
                Debug.LogError($"Error: {concreteType.Name} service must implement {typeof(T)}.");
                return default(T);
            }

            try
            {
                T serviceInstance = (T)Activator.CreateInstance(concreteType, args);
                return serviceInstance;
            }
            catch (Exception e)
            {
                Debug.LogError($"Error: Failed to instantiate {concreteType.Name}: {e.GetType()} - {e.Message}");
                return default(T);
            }
        }

        #endregion IMixedRealityServiceRegistrar implementation

        /// 
        /// Initialize a service.
        /// 
        /// The interface type for the service to be initialized.
        /// The concrete type of the service to initialize.
        /// The platform(s) on which the service is supported.
        /// Arguments to provide to the service clast constructor.
        protected virtual void Initialize(Type concreteType, SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1), params object[] args) where T : IMixedRealityService
        {
            if (!RegisterService(concreteType, supportedPlatforms, args))
            {
                Debug.LogError($"Failed to register the {concreteType.Name} service.");
            }

            T serviceInstance = FindService();
            serviceInstance?.Initialize();
        }

        /// 
        /// Uninitialize a service.
        /// 
        /// The interface type for the service to uninitialize.
        protected virtual void Uninitialize() where T : IMixedRealityService
        {
            T serviceInstance = FindService();

            if (serviceInstance != null)
            {
                registeredServices.Remove(typeof(T));
                MixedRealityServiceRegistry.RemoveService(serviceInstance, this);
            }
        }

        /// 
        /// Locates a service instance in the registry,
        /// 
        /// The interface type of the service to locate.
        /// The name of the desired service.
        /// Instance of the interface type, or null if not found.
        private T FindService(string name = null) where T : IMixedRealityService
        {
            Type interfaceType = typeof(T);
            IMixedRealityService serviceInstance;

            if (!registeredServices.TryGetValue(interfaceType, out serviceInstance)) { return default(T);  }

            return (T)serviceInstance;
         }
    }
}