OldBlueWater/BlueWater/Assets/Doozy/Editor/Common/Utils/DomainReloadHandler.cs

268 lines
11 KiB
C#
Raw Normal View History

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Doozy.Runtime.Common.Attributes;
using Doozy.Runtime.Common.Utils;
using UnityEditor;
using UnityEngine;
namespace Doozy.Editor.Common.Utils
{
public static class DomainReloadHandler
{
private static Assembly doozyEditorAssembly => ReflectionUtils.doozyEditorAssembly;
private static Assembly doozyRuntimeAssembly => ReflectionUtils.doozyRuntimeAssembly;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void OnRuntimeLoad()
{
if(!EditorSettings.enterPlayModeOptionsEnabled)
return;
// ReSharper disable NotAccessedVariable
int clearedValues = 0;
int executedMethods = 0;
// ReSharper restore NotAccessedVariable
foreach (MemberInfo member in GetMembers<ClearOnReloadAttribute>(true))
{
//Fields
{
var field = member as FieldInfo;
if (field != null && !field.FieldType.IsGenericParameter && field.IsStatic)
{
Type fieldType = field.FieldType;
ClearOnReloadAttribute reloadAttribute = field.GetCustomAttribute<ClearOnReloadAttribute>();
object valueOnReload = reloadAttribute?.ValueOnReload;
bool createNewInstance = reloadAttribute != null && reloadAttribute.CreateNewInstance;
dynamic value = valueOnReload != null ? Convert.ChangeType(valueOnReload, fieldType) : null;
if (createNewInstance) value = Activator.CreateInstance(fieldType);
try
{
field.SetValue(null, value);
}
catch
{
// ignored
}
clearedValues++;
}
}
//Properties
{
var property = member as PropertyInfo;
if (property != null && !property.PropertyType.IsGenericParameter && property.GetAccessors(true).Any(x => x.IsStatic))
{
Type fieldType = property.PropertyType;
ClearOnReloadAttribute reloadAttribute = property.GetCustomAttribute<ClearOnReloadAttribute>();
object valueOnReload = reloadAttribute?.ValueOnReload;
bool createNewInstance = reloadAttribute != null && reloadAttribute.CreateNewInstance;
dynamic value = valueOnReload != null ? Convert.ChangeType(valueOnReload, fieldType) : null;
if (createNewInstance) value = Activator.CreateInstance(fieldType);
try
{
property.SetValue(null, value);
}
catch
{
// ignored
}
clearedValues++;
}
}
}
foreach (MemberInfo member in GetMethodMembers<ExecuteOnReloadAttribute>(true))
{
var method = member as MethodInfo;
if (method == null || method.IsGenericMethod || !method.IsStatic)
continue;
method.Invoke(null, new object[] {});
executedMethods++;
}
// Debug.Log($"Cleared {clearedValues} members, executed {executedMethods} methods");
}
private static IEnumerable<MemberInfo> GetMethodMembers<TAttribute>(bool inherit) where TAttribute : System.Attribute
{
const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;
var members = new List<MemberInfo>();
//EDITOR
try
{
//Methods
members.AddRange(from t in doozyEditorAssembly.GetTypes()
where t.IsClass
where !t.IsGenericParameter
from m in t.GetMethods(flags)
where !m.ContainsGenericParameters
where m.IsDefined(typeof(TAttribute), inherit)
select m);
}
catch (ReflectionTypeLoadException)
{
//ignored
}
//RUNTIME
try
{
//Methods
members.AddRange(from t in doozyRuntimeAssembly.GetTypes()
where t.IsClass
where !t.IsGenericParameter
from m in t.GetMethods(flags)
where !m.ContainsGenericParameters
where m.IsDefined(typeof(TAttribute), inherit)
select m);
}
catch (ReflectionTypeLoadException)
{
//ignored
}
// foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
// {
// try
// {
// //Methods
// members.AddRange(from t in assembly.GetTypes()
// where t.IsClass
// where !t.IsGenericParameter
// from m in t.GetMethods(flags)
// where !m.ContainsGenericParameters
// where m.IsDefined(typeof(TAttribute), inherit)
// select m);
// }
// catch (ReflectionTypeLoadException)
// {
// //ignored
// }
// }
return members;
}
private static IEnumerable<MemberInfo> GetMembers<TAttribute>(bool inherit) where TAttribute : System.Attribute
{
const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy;
var members = new List<MemberInfo>();
//EDITOR
try
{
foreach (Type type in doozyEditorAssembly.GetTypes())
{
if (!type.IsClass) continue;
//Fields
members.AddRange(type.GetFields(flags).Cast<MemberInfo>().Where(member => member.IsDefined(typeof(TAttribute), inherit)));
//Properties
members.AddRange(type.GetProperties(flags).Cast<MemberInfo>().Where(member => member.IsDefined(typeof(TAttribute), inherit)));
//Events
members.AddRange((from eventInfo in type.GetEvents(flags) where eventInfo.IsDefined(typeof(TAttribute), inherit) select GetEventField(type, eventInfo.Name)).Cast<MemberInfo>());
}
}
catch (ReflectionTypeLoadException)
{
//ignored
}
//RUNTIME
try
{
foreach (Type type in doozyRuntimeAssembly.GetTypes())
{
if (!type.IsClass) continue;
//Fields
members.AddRange(type.GetFields(flags).Cast<MemberInfo>().Where(member => member.IsDefined(typeof(TAttribute), inherit)));
//Properties
members.AddRange(type.GetProperties(flags).Cast<MemberInfo>().Where(member => member.IsDefined(typeof(TAttribute), inherit)));
//Events
members.AddRange((from eventInfo in type.GetEvents(flags) where eventInfo.IsDefined(typeof(TAttribute), inherit) select GetEventField(type, eventInfo.Name)).Cast<MemberInfo>());
}
}
catch (ReflectionTypeLoadException)
{
//ignored
}
// foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
// {
// try
// {
// foreach (Type type in assembly.GetTypes())
// {
// if (!type.IsClass) continue;
//
// //Fields
// members.AddRange(type.GetFields(flags).Cast<MemberInfo>().Where(member => member.IsDefined(typeof(TAttribute), inherit)));
//
// //Properties
// members.AddRange(type.GetProperties(flags).Cast<MemberInfo>().Where(member => member.IsDefined(typeof(TAttribute), inherit)));
//
// //Events
// members.AddRange((from eventInfo in type.GetEvents(flags) where eventInfo.IsDefined(typeof(TAttribute), inherit) select GetEventField(type, eventInfo.Name)).Cast<MemberInfo>());
// }
//
// }
// catch (ReflectionTypeLoadException)
// {
// //ignored
// }
// }
return members;
}
private static FieldInfo GetEventField(Type type, string eventName)
{
const BindingFlags flags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic;
FieldInfo field = null;
while (type != null)
{
//Events defined as field
field = type.GetField(eventName, flags);
if (field != null && (field.FieldType == typeof(MulticastDelegate) || field.FieldType.IsSubclassOf(typeof(MulticastDelegate))))
break;
//Events defined as property { add; remove; }
field = type.GetField(EventName(eventName), flags);
if (field != null)
break;
type = type.BaseType;
}
return field;
}
private static string EventName(string eventName)
=> $"EVENT_{eventName.ToUpper()}";
}
}