mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-27 02:36:14 +00:00
提交Unity 联机Pro
This commit is contained in:
39
JNFrame2/Assets/Plugins/SRF/Scripts/Service/Attributes.cs
Normal file
39
JNFrame2/Assets/Plugins/SRF/Scripts/Service/Attributes.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using UnityEngine.Scripting;
|
||||
|
||||
namespace SRF.Service
|
||||
{
|
||||
using System;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class ServiceAttribute : PreserveAttribute
|
||||
{
|
||||
public ServiceAttribute(Type serviceType)
|
||||
{
|
||||
ServiceType = serviceType;
|
||||
}
|
||||
|
||||
public Type ServiceType { get; private set; }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public sealed class ServiceSelectorAttribute : PreserveAttribute
|
||||
{
|
||||
public ServiceSelectorAttribute(Type serviceType)
|
||||
{
|
||||
ServiceType = serviceType;
|
||||
}
|
||||
|
||||
public Type ServiceType { get; private set; }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public sealed class ServiceConstructorAttribute : PreserveAttribute
|
||||
{
|
||||
public ServiceConstructorAttribute(Type serviceType)
|
||||
{
|
||||
ServiceType = serviceType;
|
||||
}
|
||||
|
||||
public Type ServiceType { get; private set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 901f51b194db73d479d84ae26519fc20
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,7 @@
|
||||
namespace SRF.Service
|
||||
{
|
||||
public interface IAsyncService
|
||||
{
|
||||
bool IsLoaded { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08e9b59ff0ffb22488411ef5134ee325
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,91 @@
|
||||
//#define ENABLE_LOGGING
|
||||
|
||||
namespace SRF.Service
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
using Debug = UnityEngine.Debug;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
/// <summary>
|
||||
/// A service which has async-loading dependencies
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class SRDependencyServiceBase<T> : SRServiceBase<T>, IAsyncService where T : class
|
||||
{
|
||||
private bool _isLoaded;
|
||||
protected abstract Type[] Dependencies { get; }
|
||||
|
||||
public bool IsLoaded
|
||||
{
|
||||
get { return _isLoaded; }
|
||||
}
|
||||
|
||||
[Conditional("ENABLE_LOGGING")]
|
||||
private void Log(string msg, Object target)
|
||||
{
|
||||
//#if ENABLE_LOGGING
|
||||
Debug.Log(msg, target);
|
||||
//#endif
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
StartCoroutine(LoadDependencies());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked once all dependencies are loaded
|
||||
/// </summary>
|
||||
protected virtual void OnLoaded() {}
|
||||
|
||||
private IEnumerator LoadDependencies()
|
||||
{
|
||||
SRServiceManager.LoadingCount++;
|
||||
|
||||
Log("[Service] Loading service ({0})".Fmt(GetType().Name), this);
|
||||
|
||||
foreach (var d in Dependencies)
|
||||
{
|
||||
var hasService = SRServiceManager.HasService(d);
|
||||
|
||||
Log("[Service] Resolving Service ({0}) HasService: {1}".Fmt(d.Name, hasService), this);
|
||||
|
||||
if (hasService)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var service = SRServiceManager.GetService(d);
|
||||
|
||||
if (service == null)
|
||||
{
|
||||
Debug.LogError("[Service] Could not resolve dependency ({0})".Fmt(d.Name));
|
||||
enabled = false;
|
||||
yield break;
|
||||
}
|
||||
|
||||
var a = service as IAsyncService;
|
||||
|
||||
if (a != null)
|
||||
{
|
||||
while (!a.IsLoaded)
|
||||
{
|
||||
yield return new WaitForEndOfFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log("[Service] Loading service ({0}) complete.".Fmt(GetType().Name), this);
|
||||
|
||||
_isLoaded = true;
|
||||
SRServiceManager.LoadingCount--;
|
||||
|
||||
OnLoaded();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c5aaa1711d009f48a19f2db87d71b82
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,128 @@
|
||||
//#define ENABLE_LOGGING
|
||||
|
||||
namespace SRF.Service
|
||||
{
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
public abstract class SRSceneServiceBase<T, TImpl> : SRServiceBase<T>, IAsyncService
|
||||
where T : class
|
||||
where TImpl : Component
|
||||
{
|
||||
private TImpl _rootObject;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the scene this service's contents are within
|
||||
/// </summary>
|
||||
protected abstract string SceneName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Scene contents root object
|
||||
/// </summary>
|
||||
protected TImpl RootObject
|
||||
{
|
||||
get { return _rootObject; }
|
||||
}
|
||||
|
||||
public bool IsLoaded
|
||||
{
|
||||
get { return _rootObject != null; }
|
||||
}
|
||||
|
||||
[Conditional("ENABLE_LOGGING")]
|
||||
private void Log(string msg, Object target)
|
||||
{
|
||||
//#if ENABLE_LOGGING
|
||||
Debug.Log(msg, target);
|
||||
//#endif
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
StartCoroutine(LoadCoroutine());
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
if (IsLoaded)
|
||||
{
|
||||
Destroy(_rootObject.gameObject);
|
||||
}
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
protected virtual void OnLoaded() {}
|
||||
|
||||
private IEnumerator LoadCoroutine()
|
||||
{
|
||||
if (_rootObject != null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
SRServiceManager.LoadingCount++;
|
||||
#if UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
|
||||
if (Application.loadedLevelName == SceneName)
|
||||
#else
|
||||
if (UnityEngine.SceneManagement.SceneManager.GetSceneByName(SceneName).isLoaded)
|
||||
#endif
|
||||
{
|
||||
Log("[Service] Already in service scene {0}. Searching for root object...".Fmt(SceneName), this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[Service] Loading scene ({0})".Fmt(SceneName), this);
|
||||
|
||||
#if UNITY_PRO_LICENSE || UNITY_5 || UNITY_5_3_OR_NEWER
|
||||
#if UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
|
||||
yield return Application.LoadLevelAdditiveAsync(SceneName);
|
||||
#else
|
||||
yield return UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(SceneName, UnityEngine.SceneManagement.LoadSceneMode.Additive);
|
||||
#endif
|
||||
#else
|
||||
Application.LoadLevelAdditive(SceneName);
|
||||
yield return new WaitForEndOfFrame();
|
||||
#endif
|
||||
|
||||
Log("[Service] Scene loaded. Searching for root object...", this);
|
||||
}
|
||||
|
||||
var go = GameObject.Find(SceneName);
|
||||
|
||||
if (go == null)
|
||||
{
|
||||
goto Error;
|
||||
}
|
||||
|
||||
var timpl = go.GetComponent<TImpl>();
|
||||
|
||||
if (timpl == null)
|
||||
{
|
||||
goto Error;
|
||||
}
|
||||
|
||||
_rootObject = timpl;
|
||||
_rootObject.transform.parent = CachedTransform;
|
||||
|
||||
DontDestroyOnLoad(go);
|
||||
|
||||
Debug.Log("[Service] Loading {0} complete. (Scene: {1})".Fmt(GetType().Name, SceneName), this);
|
||||
SRServiceManager.LoadingCount--;
|
||||
|
||||
OnLoaded();
|
||||
|
||||
yield break;
|
||||
|
||||
Error:
|
||||
|
||||
SRServiceManager.LoadingCount--;
|
||||
Debug.LogError("[Service] Root object ({0}) not found".Fmt(SceneName), this);
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff0dcbb555990d24e9e3055e77395656
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
17
JNFrame2/Assets/Plugins/SRF/Scripts/Service/SRServiceBase.cs
Normal file
17
JNFrame2/Assets/Plugins/SRF/Scripts/Service/SRServiceBase.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace SRF.Service
|
||||
{
|
||||
public abstract class SRServiceBase<T> : SRMonoBehaviourEx where T : class
|
||||
{
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
SRServiceManager.RegisterService<T>(this);
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
SRServiceManager.UnRegisterService<T>();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4f48d5ad0a809349bd5e46160a824d3
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
530
JNFrame2/Assets/Plugins/SRF/Scripts/Service/SRServiceManager.cs
Normal file
530
JNFrame2/Assets/Plugins/SRF/Scripts/Service/SRServiceManager.cs
Normal file
@@ -0,0 +1,530 @@
|
||||
// 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_EDITOR && ((!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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Service
|
||||
{
|
||||
public object Object;
|
||||
public Type Type;
|
||||
}
|
||||
|
||||
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.Types);
|
||||
#else
|
||||
types.AddRange(assembly.GetTypes());
|
||||
#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;
|
||||
_assemblies.Clear();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
protected void OnDisable()
|
||||
{
|
||||
if (EnableLogging)
|
||||
{
|
||||
Debug.Log("[SRServiceManager] Cleaning up services");
|
||||
}
|
||||
|
||||
// Script recompile is likely in progress - clear up everything.
|
||||
foreach (Service s in _services)
|
||||
{
|
||||
IDisposable disposable = s.Object as IDisposable;
|
||||
if (disposable != null)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
|
||||
Behaviour behaviour = s.Object as Behaviour;
|
||||
if (behaviour != null)
|
||||
{
|
||||
DestroyImmediate(behaviour.gameObject);
|
||||
} else if (s.Object is Object)
|
||||
{
|
||||
DestroyImmediate(s.Object as Object);
|
||||
}
|
||||
}
|
||||
|
||||
_services.Clear(clean: true);
|
||||
}
|
||||
#endif
|
||||
|
||||
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
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83920a42d6e0f814bacbc701ae8636a5
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 16100
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
Reference in New Issue
Block a user