123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- namespace Harmony
- {
- public class Traverse<T>
- {
- private Traverse traverse;
- Traverse()
- {
- }
- public Traverse(Traverse traverse)
- {
- this.traverse = traverse;
- }
- public T Value
- {
- get => traverse.GetValue<T>();
- set => traverse.SetValue(value);
- }
- }
- public class Traverse
- {
- static AccessCache Cache;
- Type _type;
- object _root;
- MemberInfo _info;
- MethodBase _method;
- object[] _params;
- [MethodImpl(MethodImplOptions.Synchronized)]
- static Traverse()
- {
- if (Cache == null)
- Cache = new AccessCache();
- }
- public static Traverse Create(Type type)
- {
- return new Traverse(type);
- }
- public static Traverse Create<T>()
- {
- return Create(typeof(T));
- }
- public static Traverse Create(object root)
- {
- return new Traverse(root);
- }
- public static Traverse CreateWithType(string name)
- {
- return new Traverse(AccessTools.TypeByName(name));
- }
- Traverse()
- {
- }
- public Traverse(Type type)
- {
- _type = type;
- }
- public Traverse(object root)
- {
- _root = root;
- _type = root?.GetType();
- }
- Traverse(object root, MemberInfo info, object[] index)
- {
- _root = root;
- _type = root?.GetType();
- _info = info;
- _params = index;
- }
- Traverse(object root, MethodInfo method, object[] parameter)
- {
- _root = root;
- _type = method.ReturnType;
- _method = method;
- _params = parameter;
- }
- public object GetValue()
- {
- if (_info is FieldInfo)
- return ((FieldInfo)_info).GetValue(_root);
- if (_info is PropertyInfo)
- return ((PropertyInfo)_info).GetValue(_root, AccessTools.all, null, _params, CultureInfo.CurrentCulture);
- if (_method != null)
- return _method.Invoke(_root, _params);
- if (_root == null && _type != null) return _type;
- return _root;
- }
- public T GetValue<T>()
- {
- var value = GetValue();
- if (value == null) return default(T);
- return (T)value;
- }
- public object GetValue(params object[] arguments)
- {
- if (_method == null)
- throw new Exception("cannot get method value without method");
- return _method.Invoke(_root, arguments);
- }
- public T GetValue<T>(params object[] arguments)
- {
- if (_method == null)
- throw new Exception("cannot get method value without method");
- return (T)_method.Invoke(_root, arguments);
- }
- public Traverse SetValue(object value)
- {
- if (_info is FieldInfo)
- ((FieldInfo)_info).SetValue(_root, value, AccessTools.all, null, CultureInfo.CurrentCulture);
- if (_info is PropertyInfo)
- ((PropertyInfo)_info).SetValue(_root, value, AccessTools.all, null, _params, CultureInfo.CurrentCulture);
- if (_method != null)
- throw new Exception("cannot set value of method " + _method.FullDescription());
- return this;
- }
- public Type GetValueType()
- {
- if (_info is FieldInfo)
- return ((FieldInfo)_info).FieldType;
- if (_info is PropertyInfo)
- return ((PropertyInfo)_info).PropertyType;
- return null;
- }
- Traverse Resolve()
- {
- if (_root == null && _type != null) return this;
- return new Traverse(GetValue());
- }
- public Traverse Type(string name)
- {
- if (name == null) throw new ArgumentNullException("name cannot be null");
- if (_type == null) return new Traverse();
- var type = AccessTools.Inner(_type, name);
- if (type == null) return new Traverse();
- return new Traverse(type);
- }
- public Traverse Field(string name)
- {
- if (name == null) throw new ArgumentNullException("name cannot be null");
- var resolved = Resolve();
- if (resolved._type == null) return new Traverse();
- var info = Cache.GetFieldInfo(resolved._type, name);
- if (info == null) return new Traverse();
- if (info.IsStatic == false && resolved._root == null) return new Traverse();
- return new Traverse(resolved._root, info, null);
- }
- public Traverse<T> Field<T>(string name)
- {
- return new Traverse<T>(Field(name));
- }
- public List<string> Fields()
- {
- var resolved = Resolve();
- return AccessTools.GetFieldNames(resolved._type);
- }
- public Traverse Property(string name, object[] index = null)
- {
- if (name == null) throw new ArgumentNullException("name cannot be null");
- var resolved = Resolve();
- if (resolved._root == null || resolved._type == null) return new Traverse();
- var info = Cache.GetPropertyInfo(resolved._type, name);
- if (info == null) return new Traverse();
- return new Traverse(resolved._root, info, index);
- }
- public Traverse<T> Property<T>(string name, object[] index = null)
- {
- return new Traverse<T>(Property(name, index));
- }
- public List<string> Properties()
- {
- var resolved = Resolve();
- return AccessTools.GetPropertyNames(resolved._type);
- }
- public Traverse Method(string name, params object[] arguments)
- {
- if (name == null) throw new ArgumentNullException("name cannot be null");
- var resolved = Resolve();
- if (resolved._type == null) return new Traverse();
- var types = AccessTools.GetTypes(arguments);
- var method = Cache.GetMethodInfo(resolved._type, name, types);
- if (method == null) return new Traverse();
- return new Traverse(resolved._root, (MethodInfo)method, arguments);
- }
- public Traverse Method(string name, Type[] paramTypes, object[] arguments = null)
- {
- if (name == null) throw new ArgumentNullException("name cannot be null");
- var resolved = Resolve();
- if (resolved._type == null) return new Traverse();
- var method = Cache.GetMethodInfo(resolved._type, name, paramTypes);
- if (method == null) return new Traverse();
- return new Traverse(resolved._root, (MethodInfo)method, arguments);
- }
- public List<string> Methods()
- {
- var resolved = Resolve();
- return AccessTools.GetMethodNames(resolved._type);
- }
- public bool FieldExists()
- {
- return _info != null;
- }
- public bool MethodExists()
- {
- return _method != null;
- }
- public bool TypeExists()
- {
- return _type != null;
- }
- public static void IterateFields(object source, Action<Traverse> action)
- {
- var sourceTrv = Create(source);
- AccessTools.GetFieldNames(source).ForEach(f => action(sourceTrv.Field(f)));
- }
- public static void IterateFields(object source, object target, Action<Traverse, Traverse> action)
- {
- var sourceTrv = Create(source);
- var targetTrv = Create(target);
- AccessTools.GetFieldNames(source).ForEach(f => action(sourceTrv.Field(f), targetTrv.Field(f)));
- }
- public static void IterateFields(object source, object target, Action<string, Traverse, Traverse> action)
- {
- var sourceTrv = Create(source);
- var targetTrv = Create(target);
- AccessTools.GetFieldNames(source).ForEach(f => action(f, sourceTrv.Field(f), targetTrv.Field(f)));
- }
- public static void IterateProperties(object source, Action<Traverse> action)
- {
- var sourceTrv = Create(source);
- AccessTools.GetPropertyNames(source).ForEach(f => action(sourceTrv.Property(f)));
- }
- public static void IterateProperties(object source, object target, Action<Traverse, Traverse> action)
- {
- var sourceTrv = Create(source);
- var targetTrv = Create(target);
- AccessTools.GetPropertyNames(source).ForEach(f => action(sourceTrv.Property(f), targetTrv.Property(f)));
- }
- public static void IterateProperties(object source, object target, Action<string, Traverse, Traverse> action)
- {
- var sourceTrv = Create(source);
- var targetTrv = Create(target);
- AccessTools.GetPropertyNames(source).ForEach(f => action(f, sourceTrv.Property(f), targetTrv.Property(f)));
- }
- public static Action<Traverse, Traverse> CopyFields = (from, to) => { to.SetValue(from.GetValue()); };
- public override string ToString()
- {
- var value = _method ?? GetValue();
- return value?.ToString();
- }
- }
- }
|